SpringBoot使用TestRestTemplate进行测试是否总是需要@SpringBootTest批注

时间:2019-02-17 03:34:41

标签: spring-boot groovy spock spring-boot-test

我正在使用@WebMvcTest批注和MockMvc测试一个控制器,它工作正常:

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

我在线阅读了一些文章,我们可以使用TestRestTemplate进行集成测试。我的问题是,如果我使用TestRestTemplate,是否必须将其与@SpringBootTest批注一起用于SpringBoot测试?我之所以这样问,是因为我们的springBoot应用程序中有很多控制器,还有服务/ dao层代码。看来我必须为所有bean(甚至是我未测试的其他控制器的bean)创建一个TestConfigure.class来进行测试,否则,我将得到类似以下错误:

Unable to start EmbeddedWebApplicationContext 
due to missing EmbeddedServletContainerFactory bean

我使用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)

    .....
   }
 }

1 个答案:

答案 0 :(得分:0)

该错误只是告诉您,集成测试缺少用于运行您的Web服务的servlet容器。您只需要以某种方式配置此容器。您可以手动进行操作,也可以允许Spring以与使用@SpringBootApplication@EnableAutoConfiguration时相同的方式进行操作。因此,只需将@EnableAutoConfiguration放在集成测试类上,或通过在测试内部声明一个静态类并在其上标记注释来创建测试配置。如评论中所建议,以下假设是错误的

  

似乎我必须为所有bean创建一个TestConfigure.class ...

这里是没有任何用户定义的bean的工作示例,其中Spring只是为不存在的方法返回404:

@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 {

    }
}