如何对仅调用MyBatis Mapper的Service方法进行单元测试?
关于CourseService单元测试的疑问解答
嘿,作为MyBatis和单元测试的新手,你的问题非常典型,我来帮你理清楚这两个核心问题:
1. 有没有必要对courseService.getById(id)做单元测试?
绝对有必要!哪怕现在你的CourseService只是单纯转发Mapper的调用,单元测试依然有这些关键价值:
- 验证依赖注入的正确性:确保
CourseMapper能被正常Autowired到Service中,避免出现注入失败的隐性问题 - 为未来的代码变更做保障:如果以后你在Service层添加逻辑(比如参数合法性校验、返回值的额外处理、异常捕获等),现有的测试可以快速帮你验证新逻辑是否破坏了原有功能
- 养成良好的测试习惯:保持测试套件的完整性,对后续维护代码、协作开发都非常有帮助
2. Mock CourseMapper的方式是否合适?
这完全是单元测试Service层的正确姿势!单元测试的核心是隔离被测对象(这里就是CourseService),把它的外部依赖(比如CourseMapper、数据库)都Mock掉,这样测试只关注Service本身的逻辑,不会受外部资源的影响,测试速度更快、结果更稳定。
你的Mock思路没问题,不过可以简化写法让测试更清晰:
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import static org.mockito.Mockito.when; import static org.junit.jupiter.api.Assertions.assertEquals; @ExtendWith(MockitoExtension.class) public class CourseServiceTest { // Mock外部依赖CourseMapper @Mock private CourseMapper courseMapper; // 把Mock的Mapper注入到被测的CourseService中 @InjectMocks private CourseService courseService; @Test void getById_ShouldReturnExpectedCourse() { // 1. 准备测试数据 int testId = 5; Course expectedCourse = new Course(testId, true, 1, "Java基础", "入门课程", 30); // 2. 设置Mock行为:当调用mapper的getById(testId)时,返回预期的Course when(courseMapper.getById(testId)).thenReturn(expectedCourse); // 3. 调用被测方法 Course actualCourse = courseService.getById(testId); // 4. 验证结果 assertEquals(testId, actualCourse.getId()); // 你还可以根据需要断言其他字段的正确性 } }
如果确实需要动态根据入参生成返回值(比如你的示例场景),用thenAnswer也没问题,注意修正方法名的小错误即可:
when(courseMapper.getById(anyInt())) .thenAnswer(this::returnCourseWithSameIdThatInTheArgument); // 注意方法名要和引用一致,且符合Java命名规范 private Course returnCourseWithSameIdThatInTheArgument(InvocationOnMock invocation) { int id = (int) invocation.getArguments()[0]; return new Course(id, true, 1, "", "", 1); }
最后提醒一点:你的示例中Mapper接口的方法是getById,但Mock代码里写的是getCourseById,一定要保持方法名一致,不然测试会失败哦~
内容的提问来源于stack exchange,提问作者Álvaro Nieto
相关产品推荐
相关产品推荐

