Mockito - 未模拟的方法无法 return 对象本身

Mockito - Unmocked method failed to return the object itself

我有一个 Spring @RestController,它有一个 Apache Camel 接口字段 FluentProducerTemplate

我正在用 MockMvc 测试控制器,我正在注入 FluentProducerTemplate 作为模拟。

我只想模拟一种方法 - request(),并使用其他方法的实际实现。

但是,我从未模拟的方法中得到 NullPointerException。其他 FluentProducerTemplate 方法 n ,他们的 return 类型是 FluentProducerTemplate。在实施中他们 return this。模拟对象 returns null.

  1. 我认为 mockito @Mock 只模拟我指定的方法。其他方法使用原始实现。这是正确的说法吗?
  2. 我尝试了 @Spy 而不是 @Mock,但我得到了同样的错误。
  3. 当我模拟我使用的所有方法时,它就可以工作并且没有 NullPointerException

代码:

REST 控制器:

@RestController
@RequestMapping("/v1/test”)

public class MyController {


@EndpointInject(uri = "direct:main")
private FluentProducerTemplate producerTemplate;

@RequestMapping(value = “/test2”, method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public MyResponse testRequest(
        @RequestHeader(“id”) String id,
        @RequestHeader(“context”) String context,
        @RequestBody RequestBody requestBody
) {
    MyResponse response = producerTemplate
            .withHeader(“id”, id)
            .withHeader(“context”, context)
            .withBody(requestBody)
            .request(MyResponse.class);
    return response;
}

测试:

@RunWith(MockitoJUnitRunner.class)
public class MyControllerTest {

    private MockMvc mockMvc;

    @Mock
    private FluentProducerTemplate producerTemplateMock;

    @InjectMocks
    private MyControllerTest myController;

    private static MyResponse expectedResultSuccess;

    private static String requestString;

    private static HttpHeaders allRequestHeaders;

    @BeforeClass
    public static void setup() {

        allRequestHeaders = new HttpHeaders();
        allRequestHeaders.set(“id”, “123”);
        allRequestHeaders.set(“context”, “ABCD1234”);
        allRequestHeaders.set(“Content-Type”, “application/json”);

        expectedResultSuccess =  new MyResponse(“test”);

        requestString = “request”BodyText;

    }

    @Before
    public void init() {

        mockMvc = MockMvcBuilders.standaloneSetup(myController).build();

        when(producerTemplateMock.request(any())).thenReturn(expectedResultSuccess);

    }

    @Test
    public void testSuccess() throws Exception {

        mockMvc.perform(post(“/v1/test/test2)
                .headers(allRequestHeaders)
                .content(requestString))
                .andExpect(status().isOk())

    }

}

仅当我将以下内容添加到 init() 时测试通过:

  when(producerTemplateMock.withHeader(any(), any())).thenReturn(producerTemplateMock);
  when(producerTemplateMock.withBody(any())).thenReturn(producerTemplateMock);

我的主要问题是 - 为什么我必须模拟所有方法? 我更喜欢使用 withHeader()withBody() 的原始实现,并且只模拟 request().

你想要所谓的部分模拟。根据您是想主要设置模拟还是主要调用真实实现,有不同的首选方法。

1。 spy 用于少量模拟,大部分为实际实现

如果你只想模拟一些方法,否则调用真正的实现:

FluentProducerTemplate producerTemplateMock = spy(FluentProducerTemplate.class);

// Mock implementation
doReturn(expectedResultSuccess).when(producerTemplateMock).request(any());

// All other method call will use the real implementations

2。 mock 大部分是模拟,很少有实际实现

FluentProducerTemplate producerTemplateMock = mock(FluentProducerTemplate.class);

// Mock methods
when(producerTemplateMock.request(any())).thenReturn(expectedResultSuccess);

// tell mockito to call the real methods
when(producerTemplateMock.withHeader(any(), any())).thenCallRealMethod;
when(producerTemplateMock.withBody(any())).thenCallRealMethod();

如您所见,第二种方法更适合编写样板文件。但是,这取决于您的用例,哪种方法更适合。