You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);
    }
}

问题原因分析

  1. @Mock注解使用错误:
    同时用@Mock标记并手动实例化SomeController,Mockito会忽略手动实例化的对象,生成一个纯mock对象。纯mock对象的所有方法默认返回null,且不会执行真实方法逻辑,因此createReturnType调用后返回null。

  2. 测试方法命名不合法:
    JUnit测试方法名不能包含空格,test createReturnType的写法不符合规范,会导致测试执行逻辑异常。

  3. 未选择正确的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 11:24:17