本文介绍了将模拟注入Spring MockMvc WebApplicationContext的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Spring-boot测试(通过JUnit4和Spring MockMvc)REST服务适配器.适配器只是将对它的请求传递给另一个REST服务(使用自定义RestTemplate),并将其他数据附加到响应中.

I'm working to test (via JUnit4 and Spring MockMvc) a REST service adapter using Spring-boot. The adapter simply passes along requests made to it, to another REST service (using a custom RestTemplate) and appends additional data to the responses.

我想运行MockMvc测试以执行控制器集成测试,但想通过模拟覆盖控制器中的RestTemplate,以允许我预定义第三方REST响应并防止其在运行期间受到攻击每次测试.我已经能够通过实例化MockMvcBuilders.standAloneSetup()并将其传递给要测试的控制器来完成此操作,该控制器已按照此(以及下面的我的设置),但是我无法使用MockMvcBuilders.webAppContextSetup()做同样的事情.

I'd like to run MockMvc tests to perform controller integration tests, but want to override the RestTemplate in the controller with a mock to allow me to predefine the 3rd party REST response and prevent it from being hit during each test. I've been able to accomplish this by instantiating a MockMvcBuilders.standAloneSetup() and passing it the controller to be tested with the mock injected as listed in this post (and my setup below), however I am not able to do the same using MockMvcBuilders.webAppContextSetup().

我浏览过其他几篇文章,没有一篇回答关于如何实现的问题.我想使用实际的Spring应用程序上下文进行测试,而不是独立使用,以防止由于应用程序可能增长而造成任何差距.

I've been through a few other posts, none of which answer the question as to how this might be accomplished. I would like to use the actual Spring application context for the tests instead of a standalone to prevent any gaps as the application is likely to grow.

我正在使用Mockito作为我的模拟框架,并试图将其模拟之一注入到上下文中.如果没有必要,那就更好了.

I am using Mockito as my mocking framework and am trying to inject one of its mocks into the context. If this isn't necessary, all the better.

控制器:

@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正是您所需要的.

Spring's MockRestServiceServer is exactly what you're looking for.

来自javadoc的简短描述:

Short description from javadoc of the class:

尝试像这样设置测试:

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


}

这篇关于将模拟注入Spring MockMvc WebApplicationContext的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-11 04:06