简体   繁体   中英

Does SpringBoot test with TestRestTemplate always require @SpringBootTest annotation

I am testing a controller using the @WebMvcTest annotation and MockMvc, it is working fine:

@WebMvcTest(MyController.class)
class MyControllerSpec extends Specification {

@Autowired
MockMvc mockMvc;

def "test"() {
   def mockRequest = "something"

   when: "we make call"
   def response = mockMvc.perform(post("/getuser")
            .contentType(MediaType.APPLICATION_JSON)
            .content(mockRequest))
            .andReturn().response

   then: "we get response"
   response.status == OK.value()
   }
}

I read some articles online that we can use TestRestTemplate for integration testing. My question is that if I use TestRestTemplate, do I have to use it with @SpringBootTest annotation for SpringBoot test? The reason I am asking this is that we have many controllers in our springBoot application, and also the service/dao layer code. It seems that I have to create a TestConfigure.class for all the beans (even the beans for other controllers that I am not testing) for testing purpose, otherwise, I will get error like:

Unable to start EmbeddedWebApplicationContext 
due to missing EmbeddedServletContainerFactory bean

My test code using TestRestTemplate:

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, 
                classes = [TestConfigure.class])
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
class  MyControllerSpec extends Specification {

@LocalServerPort
private int port;

@Autowired
TestRestTemplate restTemplate

private String createURLWithPort(String uri) {
    return "http://localhost:" + port + uri;
}

def "Integration Success Senario"() {

    given: ""
    when: "we try to get a user using a rest call"

    def request = new User(name, address)

    String jsonResponse = 
       restTemplate.postForObject(createURLWithPort("/getuser"), 
                                  request, String.class)

    .....
   }
 }

The error just tells you that your integration test is missing a servlet container to run your web service under test. You just have to configure this container somehow. You can do it manually or allow Spring to do it the same way as it does when you use @SpringBootApplication or @EnableAutoConfiguration . So just put @EnableAutoConfiguration on your integration test class or create test configuration by declaring a static class inside the test and mark put the annotation on it. As suggested in the comment, the following assumption is wrong

It seems that I have to create a TestConfigure.class for all the beans...

Here is the working example without any user-defined beans and where Spring just returns 404 for non-existing method:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
class MyControllerSpec extends Specification {
    @LocalServerPort
    private int port

    @Autowired
    TestRestTemplate restTemplate

    def "Integration Success Senario"() {
        given: ""
        def request = new User("name", "address")

        when: "we try to get a user using a rest call"
        def response = restTemplate.postForObject(createURLWithPort("/getuser"), request, Map.class)

        then:
        response.status == 404

    }

    private String createURLWithPort(String uri) {
        return "http://localhost:" + port + uri
    }

    @EnableAutoConfiguration //it configures the servlet container
    @Configuration
    static class TestConfig {

    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM