Inject mock into Spring MockMvc WebApplicationContext

前端 未结 3 622
终归单人心
终归单人心 2021-01-31 22:00

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 (usin

相关标签:
3条回答
  • 2021-01-31 22:18

    org.springframework.boot.test.mock.mockito.MockBean @MockBean helped me out.

    0 讨论(0)
  • 2021-01-31 22:34

    Here's another solution. Simply put, it just creates a new RestTemplate bean and overrides the one already registered.

    So while it performs produces the same functionality as @mzc answer, it allows me to use Mockito to craft the response and verification matchers a bit easier.

    Not that it's more than a couple lines of code, but it also prevents from having to add additional code to convert from the Response object to a string for the above mockRestServiceServer.expect().andRespond(<String>) method's arg.

    @RunWith(SpringJUnit4ClassRunner.class)
    @WebAppConfiguration
    @SpringApplicationConfiguration(classes = MainSpringBootAdapter.class)
    @TestPropertySource("/application-junit.properties")
    public class WacControllerTest {
    
        private static String Controller_URL = Constants.REQUEST_MAPPING_PATH + Constants.REQUEST_MAPPING_RESOURCE + compressedParams_all;
    
        @Configuration
            static class Config {
                @Bean
                @Primary
                public RestTemplate restTemplateMock() {
                    return Mockito.mock(RestTemplate.class);
            }
        }
    
        @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.webAppContextSetup(this.wac).build();
            this.rt = (RestTemplate) this.wac.getBean("restTemplateMock");
        }
    
        @Test
        public void testGetResponse() throws Exception {
    
            String[] strings = {"request", "100"};
    
            //Set the request params from the client request
            Map<String, String> parameters = new HashMap<String, String>();
            parameters.put(Constants.PARAM_SINGLELINE, strings[0]);
            parameters.put(Constants.PARAM_FORMAT, Constants.PARAMS_FORMAT.JSON);
    
            Mockito.when(
                rt.getForObject(Mockito.<String> any(), Mockito.<Class<Object>> any(), Mockito.<Map<String, ?>> any()))
                .thenReturn(populateTestResponse());
    
            mockMvc.perform(get(Controller_URL, 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;
        }
    }
    
    0 讨论(0)
  • 2021-01-31 22:38

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

    Short description from javadoc of the class:

    Main entry point for client-side REST testing. Used for tests that involve direct or indirect (through client code) use of the RestTemplate. Provides a way to set up fine-grained expectations on the requests that will be performed through the RestTemplate and a way to define the responses to send back removing the need for an actual running server.

    Try to set up your test like this:

    @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));
        }
    
    
    }
    
    0 讨论(0)
提交回复
热议问题