引入Spring-test-starter即可引入 Junit+Mockito+assertJ
业务逻辑层的单元测试
分析业务逻辑层的职责: 被controller层进行调用后; 1.校验数据 2.执行业务逻辑 - 调用其他原子服务的接口 - 组装数据 - 执行对应的操作 3.执行数据库操作 举个例子:创建订单createOrder()
public class OrderService {
public Boolean createOrder(CreateOrderRequest req) {
checkOrderRequestParamter(req);
UserMsg userMsg = userFacade.getUser(req.getUserId);
fillOrderUserMsg(req,userMsg);
List<GoodMsg> goods = GoodsFacade.getGoods(req.getItemsSkuSn());
checkAndFillGoodsMsg(goods,req);
calculatedAmount(req);
orderMapper.createOrder(req);
}
}
- servcie层单元测试的目的:
测试中间的业务逻辑是否正确的执行,没有过度执行也没有遗漏业务逻辑;主要是对方法中的业务逻辑进行测试 而不是需要订单真正的落库,那是mapper单元测试需要测试的内容,需要界定你单元测试的范围;也不需要去看对应商品服务接口返回的数据是否有误; - 单元测试的局限性:
一般单元测试都是由开发在本地进行测试自己的代码,而像一些请求接口并不能去调用,类似于上述例子中:需要获取用户信息或者商品信息,由于是微服务开发,我们不一定能在本地直接去调用对应的接口;那么这个应该如何测试呢? 有两种方法,也是在总览中提到的: 一种是桩代码:也就是在单元测试的时候,将对应的接口调用替换成一段测试专门使用的创建对应的参数进行返回,但不过这样做事有坏处的,如果在发布的时候,忘记将其改回来就会产生问题;所以更推荐的方法是第二种 二:Mock对象;使用上述的工具Mockito;对调用的其他的微服务接口进行模拟对象;其执行原理大致是:动态生成一个被模拟对象相同类型的对象,注入到ioc容器中将其替换,然后我们在书写调用执行对应方法时的业务逻辑;
上述已经论述了为什么使用Mockito的原因与其作用了;那么为什么使用断言呢? 问题: 如何判断单元测试是否执行成功呢? 将结果进行输出System.out.println();由人工去判断是否得到自己想要的结果;那么随着业务系统规模的增大,单元测试越来越多,我们使用maven插件mvn:test一键自动化执行所有的单元测试,在一个一个去进行比较单元测试是否成功是一件很花费时间的事情; 解决:使用断言 断言的作用:比较方法得出的结果与我们预期的结果是否一致,减少用人眼去校对的过程;也就是assertJ的作用;
但具体的对应的方法,本文就不涉及了;
那么业务逻辑层的单元测试还有什么需要注意的? 注意单元测试的覆盖率;由于业务逻辑层的代码相较于其他层是较多的(不同的公司具有不同的规范,业务的复杂度也是不一样的,划分的层次也是不一样的);更需要注重测试的用例是否覆盖了大部分的代码,每一种业务场景是否都有覆盖
最后在给出一个Service层单元测试的例子吧:(基于SpringBoot)
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.*;
@RunWith(SpringRunner.class)
@SpringBootTest
public class EmployeeServiceTest {
@Autowired
private EmployeeService employeeService;
@MockBean
private EmployeeMapper employeeMapper;
@Test
public void testService() {
int employeeId = 1;
Employee employee = new Employee();
employee.setId(1);
employee.setName("张三");
employee.setAge(20);
given(this.employeeMapper.findById(anyLong()))
.willReturn(employee);
Employee resultEmployee = employeeService.findById(employeeId);
assertEquals(employee, resultEmployee);
}
}
由此Junit框架去搭建单元测试环境;Mockito去进行模拟接口对象实现方法直接的隔离,让我们单元测试的目标更加单一;assert断言判断结果是否正确,让测试的结果一目了然;
这个例子的测试显得有点多余了,因为这是一个简单的crud吧,如果类似于上面的创建订单的单元测试,其构造对象,mock接口都是十分繁琐的吧。单元测试的作用:也不仅仅只是当下之功,如果单元测试对应的代码需要增加功能,或者修改部分逻辑,你只需要运行对应的单侧就可以知道,增加的代码会不会影响之前的代码了。
|