Mockito模拟方法返回null问题排查:Spring Controller单元测试异常
问题:JUnit+Mockito测试Spring Controller方法返回null排查
原Controller代码
@Controller public class SomeController extends BaseController { @RequestMapping(method=POST, value="/something") public @ResponseBody SomeReturnType createReturnType(@RequestBody SomeReqBody someReqBody, Object obj) { // 注意@RequestBody首字母大写 return someMethod(someReqBody,"SomeString"); } public SomeReturnType someMethod(SomeReqBody someReqBody, String someString) { return someProtectedMethodFromBaseController(someReqBody, someString); } }
原测试类代码
@RunWith(MockitoJUnitRunner.class) public class testSomeController { @Mock SomeController someControllerMock = new SomeController(); @Test public void test createReturnType() { SomeReqBody someReqBody = mockRequestBody(); SomeReturnType someReturnType = mockRetruntype(); Object someObject = mockObject(); when(someControllerMock.someMethod(someReqBody,"SomeString")).thenReturn(someReturnType); SomeReturnType returnTypeExp = someControllerMock.createReturnType(someReqBody, someObject); assertNotNull(returnTypeExp); } }
问题原因分析
@Mock注解使用错误:
同时用@Mock标记并手动实例化SomeController,Mockito会忽略手动实例化的对象,生成一个纯mock对象。纯mock对象的所有方法默认返回null,且不会执行真实方法逻辑,因此createReturnType调用后返回null。测试方法命名不合法:
JUnit测试方法名不能包含空格,test createReturnType的写法不符合规范,会导致测试执行逻辑异常。未选择正确的Mock类型:
要测试createReturnType的真实逻辑,同时mocksomeMethod的返回值,应该使用@Spy(间谍对象)而非@Mock。Spy会保留真实对象的方法行为,仅对指定方法进行stub。
修正后的测试类代码
@RunWith(MockitoJUnitRunner.class) public class TestSomeController { // 类名首字母大写,符合Java规范 @Spy // 使用Spy保留真实对象逻辑,仅stub指定方法 SomeController someControllerSpy = new SomeController(); @Test public void testCreateReturnType() { // 修正方法名,移除空格 // 创建测试用的mock对象 SomeReqBody someReqBody = mock(SomeReqBody.class); SomeReturnType someReturnType = mock(SomeReturnType.class); Object someObject = new Object(); // 对someMethod进行stub,避免执行真实方法逻辑 doReturn(someReturnType).when(someControllerSpy).someMethod(someReqBody, "SomeString"); // 调用真实的createReturnType方法 SomeReturnType returnTypeExp = someControllerSpy.createReturnType(someReqBody, someObject); // 断言验证 assertNotNull(returnTypeExp); assertEquals(someReturnType, returnTypeExp); // 验证返回值符合预期 } }
额外注意事项
- Controller中的
@Requestbody需改为@RequestBody(首字母大写),否则会出现编译错误。 - 使用Spy时,推荐用
doReturn(...).when(spy).method(...)的方式stub方法,而非when(spy.method(...)).thenReturn(...),后者会先执行一次真实方法,可能引发不必要的副作用。 - 测试类名需遵循Java大驼峰命名规范,改为
TestSomeController。
内容的提问来源于stack exchange,提问作者Anzz
相关产品推荐
相关产品推荐

