当要进行单元测试时,需要给A注入B和C,但是C又依赖D,D又依赖E。这就导致了,A的单元测试不满足独立性原则。 但使用了Mock来进行模拟对象后,就可以把这种依赖解耦,只关心A本身的测试,它所依赖的B和C,全部使用Mock出来的对象,并且给MockB和MockC指定一个明确的行为。
在单元测试工具的选择方面,随行付单元测试借助Junit工具和Mockito工具进行单元测试,微服务架构下不管是spring boot还是spring cloud,通常使用@SpringBootTest注解进行单元测试。一个单元测试的实现步骤主要包括4步:
1.设置测试数据
2.Mock依赖的系统并给定预期值,如果没有依赖这步可以省略
3.在测试中调用方法
4.断言返回的结果是否符合预期
下面以一个非常简单的例子介绍在微服务架构下如何对spring boot中的controller层和service层进行单元测试。
调用逻辑简化版如图所示,Controller调用ServiceA,ServiceA依赖ServiceB。
被依赖ServiceB的代码如下
package cn.vbill.quality.service; import org.springframework...Service; @Service public class ServiceB { public boolean serve(int param) { return param % 2 == 0; } } |
被测ServiceA的代码如下
package cn.vbill.quality.service; import org.springframework.beans...Autowired; import org.springframework.stereotype.Service; @Service public class ServiceA { @Autowired private ServiceB srvB; public String doSomething(int param) { if (srvB.serve(param)) { return "even"; } return "obb"; } } |
ServiceA和ServiceB的逻辑非常简单,现在测试ServiceA,步骤如下:
首先:在gradle中增加测试需要的依赖包
// 可根据实际情况添加版本号
testCompile("org.springframework.boot:spring-boot-starter-test")
其次:在src/test/java下面创建测试类,采用@SpringBootTest注解和Mockito技术对ServiceB进行测试和Mock,更多Mockito的使用可以参考其他文章,这里不过多介绍。代码如下:
最后,使用覆盖率工具查看单元测试覆盖率,如下图所示,实现了100%覆盖。
ServiceB没有任何依赖,因此对它测试就按照常规的Junit测试即可,这里不过多介绍。下面介绍Controller层的单元测试,整体上看 Controller 层的测试和 Service 层大致相同,只不过是我们不去直接调用 Controller 的方法,而是通过MockMvc模拟HTTP请求。从逻辑图上看Controller是直接调用ServiceA,因此需要使用Mockito模拟ServiceA。
被测Controller代码逻辑如下:
测试类如下
最后,通过覆盖率工具查看单元测试覆盖率为100%,做到了全覆盖。
以上是如何在微服务架构下进行单元测试进行了详细的介绍,在微服务架构下高覆盖率的单元测试是保障代码质量的第一道也是最重要的关口,应该持之以恒。
总结
本篇分别从微服务架构下开展单元测试的意义、对单元测试的常见误解以及如何开展单元测试三个方面进行介绍,单元测试是一项成本低、收益高的实践,要利用好这把利剑,打好代码质量基础,为后续的质量保证过程添砖加瓦。
上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。