如何对基本上一对一调用 MyBatis Mapper 接口的服务方法进行单元测试

How to unit test service methods that are basically 1 to 1 calls to a MyBatis Mapper interface

我是 MyBatis 和单元测试的新手。

我有一个 CourseService class,它(目前)只有调用的方法和 return MyBatis Mapper (CourseMapper) 的等价方法。

课程服务class.

@Autowired
private CourseMapper courseMapper;

public Course getById(int id) {
    return courseMapper.getById(id);
}
...

CourseMapper 界面。

@Select("select from courses where id = #{id}")
public Course getById(int id);
...

我应该对 courseService.getById(id) 进行单元测试吗?模拟 Mapper 并使用该映射器构建服务并模拟调用 getById return 一个带有 id 作为参数传递的课程是否合适?

when(courseMapper.getCourseById(anyInt()))
    .thenAnswer(this::returnCourseWithSameIdThatInTheArgument); 
...

private Course CourseWithSameIdThatInTheArgument(InvocationOnMock i) {
    return new Course((int)i.getArguments()[0],true,1,"","",1);
}

提前致谢。

理想情况下,您应该模拟 CourseMapper 并验证 courseMapper.getById(id) 是否按预期 id

被调用一次

像这样

Mockito.verify(courseMapper, Mockito.times(1)).getById(id)

这样做的原因是 - CourseMapper 是一个不同的 class,您可以假设它已经过良好测试。您在这里所做的是阻止 CourseMapper.getById() 不需要的行为。

总的来说,关于验证的规则:

期待 Mocks 的某些行为,而不是 Stubs。

由于存根也可能记录行为,因此很想对它们执行一些验证。

您需要记住,它们的唯一目的是为稍后的处理或命令调用提供数据(这是被测 class 的实际功能)。

查询不会改变世界,因此可以调用任意次数,包括 none。

另一方面,命令调用(在 Mocks 上调用)可能会产生副作用,并且会改变目标对象之外的世界。

您正在尝试测试违反该规则的存根。