在我正在工作的应用程序中,我们必须使用来自Web服务的一些数据,对其进行处理,然后将其发送到前端。现在我正试图编写一个集成测试,它必须检查发送到前端的值的正确性。
我能够加载应用程序上下文做:
@Inject
private WebApplicationContext wac;
@BeforeMethod
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac)
.addFilters(this.springSecurityFilterChain).build();
}
之后,如果我做一些类似的事情:
mockMvc.perform(get("/url"))
.andDo(print())
.andExpect(status().isOk())
它运行得很好,我得到了与浏览器相同的响应。
为了使用来自另一个API的数据,我使用RestTemplate.getForObjetct
方法。因此,我想知道是否有一种方法可以拦截对该方法的调用并模拟答案。
我将编写两个新类——RestTemplateWrapper
和RestTemplateWrapperFactory
。前者的内部应该有一个RestTemplate
,并且只暴露出RestTemplate
中您想要与之交互的部分,包括getForObject
。要实例化RestTemplateWrapper
,您将使用RestTemplateWrapperFactory
。
现在,任何创建RestTemplate
对象的类都应该进行重构,以允许注入RestTemplateWrapperFactory
,并且只与它创建的RestTemplateWrapper
对象交互。
到了测试的时候,您将使用Mockito或EasyMock等mocking框架来创建一个mock RestTemplateWrapperFactory
,并将其存根,以便它创建RestTemplateWrapper
的mock,以及您想要的getForObject
的任何行为。然后将您的模拟RestTemplateWrapperFactory
注入到您正在测试的任何类中。
我认为您应该能够通过在您的服务实例上使用Mockito @InjectMocks
注释提供RestTemplate
的@Mock
来实现您想要的,而不必在RestTemplate
周围使用任何包装器。
因此,我建议您的测试类如下所示:
@Inject
private WebApplicationContext wac;
/* Inject your service implementation from your Spring ApplicationContext*/
@InjectMocks
@Inject
private MyService myService;
/* This Mock RestTemplate will be injected into your service instance by Mockito */
@Mock
private RestTemplate restTemplate;
@BeforeMethod
public void setup() throws Exception
{
MockitoAnnotations.initMocks(this);
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac)
.addFilters(this.springSecurityFilterChain).build();
}
这里实际发生的事情:
- 您正常构建ApplicationContext
- 您将ApplicationContext中对服务实现的引用注入到测试中
- 您使用Mockito的
@Mock
实现在测试上下文中创建一个MockRestTemplate
实例 - 将
@InjectMocks
注释放在您的MyService实现上对Mockito说:"在可能的情况下,将Mocks注入到这个实例中。" - Mockito将Mock
RestTemplate
注入您的服务实例
然后,您可以继续正常编写测试,然后使用Mockito模拟RestTemplate
的操作并验证它们,例如
@Test
public void testServiceUsesRestTemplateProperly()
{
Mockito.when(restTemplate.getForObject("http://example.com", String.class)).thenReturn("hello world");
String s = myService.doSomething();
Assert.assertEquals("hello world", s);
Mockito.verify(restTemplate).getForObject("http://example.com", String.class);
}
(如果我在这里混合了jUnit语法,我深表歉意)
更多值得阅读的信息:
- InjectMocks文档