测试驱动开发(TDD)在微服务中的应用
在上一篇文章中用一个计算长方形面积的小例子介绍了如何使用TDD,感兴趣的小伙伴可以去阅读一下,今天主要介绍TDD是如何应用在微服务中的。我们还是先来回归一下TDD的三条实践准则。
TDD的三条准则
- 除非为了使一个失败的单元测试通过,否则不允许编写任何业务代码。
- 在一个单元测试中,只允许写一个刚好导致失败的内容。
- 只允许编写刚好能够使一个失败的单元测试通过的业务代码。
开发环境
- Java 8
- Spring Boot 2.1.x
- Spring Data JPA 2.0.9
- TestNG 6.13
- Mockito 1.10.19(创建虚拟对象,解耦依赖的类或者接口)
1.编写测试用例
@InjectMocks
SageTaxService sageTaxService = new SageTaxServiceImpl();
@Mock
SageTaxRepository sageTaxRepository;
@Mock
CommonService commonService;
@Mock
WebContext webContext;
@Test
public void test_add_sage_tax() {
UserInfo userInfo = new UserInfo();
userInfo.setUserId(999);
Mockito.when(webContext.getUserInfo()).thenReturn(userInfo);
SageTax sageTax = new SageTax();
sageTax.setEntryId(webContext.getUserInfo().getGlobalUserId());
sageTax.setEntryDatetime(commonService.getDbTimestamp());
sageTax.setTaxRate(BigDecimal.valueOf(0.011));
sageTax.setTaxIdCode("test");
sageTax.setCountryCode("CA");
sageTax.setTaxCode("qqq");
Mockito.when(sageTaxRepository.save(sageTax)).thenReturn(sageTax);
Assert.assertNotNull(sageTaxService.addSageTax(sageTax));
}
2.运行测试用例
就会看到测试case运行失败了(因为你还没写功能代码)
3.编写业务代码
@Override
public Boolean addSageTax(SageTax sageTaxVO) {
List<SageTax> sageTaxList = Lists.newArrayList();
if (sageTaxVO.getCountryCode() != null && sageTaxVO.getTaxCode() != null) {
// countryCode and taxCode is unique key
sageTaxList = getSageTax(sageTaxVO.getCountryCode(), sageTaxVO.getTaxCode());
}
if (sageTaxList.size() > 0) {
// if has data in DB, return false
return false;
}
SageTax sageTax = new SageTax();
sageTax.setEntryId(webContext.getUserInfo().getGlobalUserId());
sageTax.setEntryDatetime(commonService.getDbTimestamp());
sageTax.setTaxId(sageTaxVO.getTaxId());
sageTax.setTaxIdCode(sageTaxVO.getTaxIdCode());
sageTax.setCountryCode(sageTaxVO.getCountryCode());
sageTax.setTaxCode(sageTaxVO.getTaxCode());
sageTax.setTaxRate(sageTaxVO.getTaxRate());
sageTaxRepository.save(sageTax);
return true;
}
4.运行测试用例,然后看到测试用例通过了
5.对代码查缺补漏,进行重构
补充测试用例,因为可能在保存的时候会出错,所以新增一个case用来覆盖抛出exception的情况。
@Test(expectedExceptions = Exception.class)
public void test_add_sage_tax_with_exception() {
UserInfo userInfo = new UserInfo();
userInfo.setUserId(999);
Mockito.when(webContext.getUserInfo()).thenReturn(userInfo);
SageTax sageTax = new SageTax();
sageTax.setEntryId(webContext.getUserInfo().getGlobalUserId());
sageTax.setEntryDatetime(commonService.getDbTimestamp());
sageTax.setTaxRate(BigDecimal.valueOf(0.011));
sageTax.setTaxIdCode("test");
sageTax.setCountryCode("CA");
sageTax.setTaxCode("qqq");
Mockito.when(sageTaxRepository.save(sageTax)).thenThrow(new Exception());
Mockito.when(sageTaxService.addSageTax(sageTaxVO)).thenThrow(new Exception());
}
完善业务代码
总结和心得
- 测试用例就是设计,因为每一个测试用例就是一个小的业务场景,大的业务也是由小的业务累积起来的。
- TDD 要求开发人员按照测试,开发,重构,测试,开发,重构。。。。的过程来工作,一点一滴的完成设计。
- 推翻了瀑布式的开发(先写功能代码,遇到编译错误的地方,就直接Debug项目,然后让其编译通过),站在用户的角度上进行工作。
- 完善的安全网,不用担心重构代码的时候出错。
小技巧
通常写完测试用例,我们都需要看一下我们代码的覆盖率,通常市面上常用的工具是SonarQube
,但是我们的IDEA也可以看到我们代码覆盖率。如下:
- 选中xxxxTest.java,右键Run “xxxxTest.java” with Coverage。
- 查看覆盖率,通常来说90%覆盖就好了。
还没有评论,来说两句吧...