使用 Mockito 比easyMock 更简单
使用 PowerMock 可模拟静态、私有方法
使用spring-test-dbunit 可以实现注解方式导入xml 到数据库,为数据库提供测试数据如:
@DatabaseSetup @DatabaseTearDown
使用hsqldb 内置数据库,不会导致数据被误删或其它误操作后导致单元测试跑不过。
具体实现
1、maven 依赖<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>3.2.4.RELEASE</version> <scope>test</scope> </dependency> <dependency> <groupId>org.dbunit</groupId> <artifactId>dbunit</artifactId> <version>2.4.9</version> <scope>test</scope> </dependency> <dependency> <groupId>com.github.springtestdbunit</groupId> <artifactId>spring-test-dbunit</artifactId> <version>1.0.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.hsqldb</groupId> <artifactId>hsqldb</artifactId> <version>2.3.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4-rule-agent</artifactId> <version>1.5.5</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-all</artifactId> <version>${mockito.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4</artifactId> <version>${powermock.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito</artifactId> <version>${powermock.version}</version> <scope>test</scope> </dependency>
2、单元测试父类BaseSpringTest
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:spring/bcs-spring-context-test.xml") @TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, DbUnitTestExecutionListener.class }) @Transactional public abstract class BaseSpringTest { }
3、编写单元测试
用 hsqldb 时候注意@PrepareForTest({ HttpClientUtil.class })//使用powermock public class IdCardValidateServiceImplTest extends BaseSpringTest { @Resource @InjectMocks //把被模拟对象注入 private IdCardValidateService idCardValidateService; @Resource private AppConfig appConfig; @Mock //被模拟对象 private SequenceDao sequenceDao; @Rule //spring 与 powermock 组合需要使用PowerMockRule public PowerMockRule rule = new PowerMockRule(); private static final String MOCK_RETURN_SUCC_XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><result><returnCode>0000</returnCode><userCode>043101180050000</userCode><validateType>01</validateType><checkPhoto>3xf89Hoqpk0VIH/9k=</checkPhoto><traceNo>1001123</traceNo><responseDatetime>20150120154442</responseDatetime><Sign>C0AED4A3EE24D4913C71E6DBD323D1EB</Sign></result>"; @Before public void setUp() { MockitoAnnotations.initMocks(this); PowerMockito.mockStatic(HttpClientUtil.class);//使用powermock 模拟静态类 } //正常流程,先查库,库里没有再调接口。库里面没有该身份证信息 @Test @DatabaseSetup({"classpath:/dbunit/T_BCS_IDCARD_INFO.xml", "classpath:/dbunit/T_BCS_PLAT.xml"}) @DatabaseTearDown(value = {"classpath:/dbunit/T_BCS_IDCARD_INFO.xml", "classpath:/dbunit/T_BCS_PLAT.xml"},type = DatabaseOperation.TRUNCATE_TABLE) public void testValidate() throws Exception { String seq =RandomStringUtils.randomNumeric(7); Mockito.when(sequenceDao.getIdcardLogSeq()).thenReturn(Long.valueOf(seq));//Mockito模拟返回 Mockito.when(sequenceDao.getIdcardInfoSeq()).thenReturn(Long.valueOf(seq));//Mockito模拟返回 IdCardReq req = new IdCardReq(); req.setReqSeq("123"); req.setPlatCode("1001"); req.setRequestTime(new Date()); req.setNeedPhoto(false); IDCardVO idCardVO = new IDCardVO(); idCardVO.setIdentityNo("430022198509136854"); idCardVO.setIdentityType("00"); idCardVO.setRealName("刘德华"); req.setIdCard(idCardVO); List params = IdCardValidateServiceImpl.getParamList(req, appConfig); //PowerMock模拟返回 PowerMockito.when(HttpClientUtil.doPost(appConfig.getGztUrl(),params,"UTF-8")).thenReturn(MOCK_RETURN_SUCC_XML); BcsResponse<IdCardRes> res = idCardValidateService.validate(req); Assert.assertEquals(ErrorCodeEnum.SUCCEED_CODE.getErrorcode(),res.getErrorCode()); Assert.assertEquals(ErrorCodeEnum.SUCCEED_CODE.getErrordesc(),res.getErrorMsg()); } }
数据类型区别
oracle hsqldb
varchar2 varchar
number NUMERIC
date TIMESTAMP
另外hsqldb获取sequence与oracle方式不一样,所以需要模拟