我有一个Spring @RestController
,它具有Apache Camel接口FluentProducerTemplate
的字段。
我正在用MockMvc
测试控制器,并以模拟方式注入FluentProducerTemplate
。
我只想模拟一个方法-request()
,并使用其他方法的实际实现。
但是,我从未经模拟的方法中获得了NullPointerException
。其他FluentProducerTemplate
方法n ,其返回类型为FluentProducerTemplate
。在实现中,它们返回this
。模拟对象返回null。
@Mock
仅模仿我指定的方法。其他方法使用原始实现。这是正确的说法吗?@Spy
而不是@Mock
,并且遇到相同的错误。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()
。
您想要所谓的局部模拟。根据您是要设置大多数模拟还是大部分调用真实的实现,有不同的首选方法。
spy
少量模拟,大部分为实际实现如果只想模拟某些方法,否则调用真正的实现:
FluentProducerTemplate producerTemplateMock = spy(FluentProducerTemplate.class);
// Mock implementation
doReturn(expectedResultSuccess).when(producerTemplateMock).request(any());
// All other method call will use the real implementations
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();
如您所见,第二种方法是编写更多样板。但是,这取决于您的用例,哪种方法更合适。