我正在尝试使用Spring-boot测试(通过JUnit4和Spring MockMvc)REST服务适配器。适配器仅RestTemplate将对它的请求传递给另一个REST服务(使用custom ),并将其他数据附加到响应中。
RestTemplate
我想运行MockMvc测试以执行控制器集成测试,但想RestTemplate通过模拟覆盖控制器中的,以允许我预定义第三方REST响应并防止在每次测试期间都被击中。我已经能够通过实例化一个做到这一点MockMvcBuilders.standAloneSetup(),并把它传递给注射了在此列出的模拟测试控制器后(和我的设置如下图),但我无法做到使用相同的MockMvcBuilders.webAppContextSetup()。
MockMvc
MockMvcBuilders.standAloneSetup()
MockMvcBuilders.webAppContextSetup()
我浏览过其他几篇文章,都没有回答有关如何实现的问题。我想使用实际的Spring应用程序上下文进行测试,而不是使用独立的上下文来防止任何差距,因为应用程序可能会增长。
编辑:我正在使用Mockito作为我的模拟框架,并试图将其模拟之一注入上下文。如果没有必要,那就更好了。
控制器:
@RestController @RequestMapping(Constants.REQUEST_MAPPING_PATH) public class Controller{ @Autowired private DataProvider dp; @Autowired private RestTemplate template; @RequestMapping(value = Constants.REQUEST_MAPPING_RESOURCE, method = RequestMethod.GET) public Response getResponse( @RequestParam(required = true) String data, @RequestParam(required = false, defaultValue = "80") String minScore ) throws Exception { Response resp = new Response(); // Set the request params from the client request Map<String, String> parameters = new HashMap<String, String>(); parameters.put(Constants.PARAM_DATA, data); parameters.put(Constants.PARAM_FORMAT, Constants.PARAMS_FORMAT.JSON); resp = template.getForObject(Constants.RESTDATAPROVIDER_URL, Response.class, parameters); if(resp.getError() == null){ resp.filterScoreLessThan(new BigDecimal(minScore)); new DataHandler(dp).populateData(resp.getData()); } return resp; } }
测试类别:
@RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @SpringApplicationConfiguration(classes = MainSpringBootAdapter.class) @TestPropertySource("/application-junit.properties") public class WacControllerTest { private static String controllerURL = Constants.REQUEST_MAPPING_PATH + Constants.REQUEST_MAPPING_RESOURCE + compressedParams_all; private static String compressedParams_all = "?data={data}&minScore={minScore}"; @Autowired private WebApplicationContext wac; private MockMvc mockMvc; @InjectMocks private Controller Controller; @Mock private RestTemplate rt; @Value("${file}") private String file; @Spy private DataProvider dp; @Before public void setup() throws Exception { dp = new DataProvider(file); MockitoAnnotations.initMocks(this); this.mockMvc = MockMvcBuilders.standaloneSetup(controller).build(); } @Test public void testGetResponse() throws Exception { String[] strings = {"requestData", "100"}; Mockito.when( rt.getForObject(Mockito.<String> any(), Mockito.<Class<Object>> any(), Mockito.<Map<String, ?>> any())) .thenReturn(populateTestResponse()); mockMvc.perform(get(controllerURL, strings) .accept(Constants.APPLICATION_JSON_UTF8)) .andDo(MockMvcResultHandlers.print()); Mockito.verify(rt, Mockito.times(1)).getForObject(Mockito.<String> any(), Mockito.<Class<?>> any(), Mockito.<Map<String, ?>> any()); } private Response populateTestResponse() { Response resp = new Response(); resp.setScore(new BigDecimal(100)); resp.setData("Some Data"); return resp; } }
Spring MockRestServiceServer正是您想要的。
MockRestServiceServer
来自javadoc的简短描述:
客户端REST测试的主要入口点。用于涉及直接或间接(通过客户端代码)使用RestTemplate的测试。提供了一种对将通过RestTemplate执行的请求设置细粒度期望的方法,以及一种定义发送回响应的方法,从而消除了对实际运行的服务器的需求。
尝试像这样设置测试:
@WebAppConfiguration @ContextConfiguration(classes = {YourSpringConfig.class}) @RunWith(SpringJUnit4ClassRunner.class) public class ExampleResourceTest { private MockMvc mockMvc; private MockRestServiceServer mockRestServiceServer; @Autowired private WebApplicationContext wac; @Autowired private RestOperations restOperations; @Before public void setUp() throws Exception { mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); mockRestServiceServer = MockRestServiceServer.createServer((RestTemplate) restOperations); } @Test public void testMyApiCall() throws Exception { // Following line verifies that our code behind /api/my/endpoint made a REST PUT // with expected parameters to remote service successfully expectRestCallSuccess(); this.mockMvc.perform(MockMvcRequestBuilders.get("/api/my/endpoint")) .andExpect(status().isOk()); } private void expectRestCallSuccess() { mockRestServiceServer.expect( requestTo("http://remote.rest.service/api/resource")) .andExpect(method(PUT)) .andRespond(withSuccess("{\"message\": \"hello\"}", APPLICATION_JSON)); } }