簡體   English   中英

Spring Boot 單元測試構造函數注入

[英]Spring Boot unit test constructor injection

我正在使用 Spring Boot 創建一個 REST API 並在我的控制器上編寫一些單元測試。 我知道在spring中注入bean的推薦方式是構造函數注入。 但是當我將@SpringBootTest注釋添加到我的測試類時,我無法用構造函數注入我的控制器類,我發現自己不得不使用@Autowired

有一些解釋,還有另一種方法可以將構造函數注入與SpringBootTest一起使用。

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class PersonControllerTest {

    @LocalServerPort
    private int port;

    @Autowired
    private PersonController controller;

    @Autowired
    private TestRestTemplate restTemplate;


    @Test
    public void greetingShouldReturnDefaultMessage() throws Exception {
        assertThat(this.restTemplate.getForObject("http://localhost:" + port + "/cvtech/Persons/",
                                                  String.class)).contains("content");
    }

    @Test
    public void contextLoads() throws Exception {
        assertThat(controller).isNotNull();
    }
    @Test
    void findAllByJob() {
    }
}

您的測試可以使用字段注入,因為測試本身不屬於您的域; 該測試不會成為您的應用程序上下文的一部分。

您不想使用SpringBootTest來測試控制器,因為這將連接所有可能過於繁重和耗時的 bean。 相反,您可能只想創建控制器及其依賴項。

所以你最好的選擇是使用@WebMvcTest ,它只會創建測試指定控制器所需的bean。

@ExtendWith(SpringExtension.class)
@WebMvcTest(controllers = PersonController.class)
class PersonControllerTest {
    @Autowired
    private MockMvc mockMvc;

    @Test
    public void greetingShouldReturnDefaultMessage() throws Exception {
        mockMvc.perform(get("/cvtech/Persons"))
               .andExpect(status().isOk())
               .andExpect(content().string(contains("content")));
    }
}

請注意, @WebMvcTest將搜索帶有@SpringBootConfiguration注釋的類,因為它是默認配置。 如果它沒有找到它,或者您想手動指定一些配置類,也可以使用@ContextConfiguration注解測試。

此外,作為旁注,使用TestRestTemplate時,您不需要指定主機和端口。 只需調用restTemplate.getForObject("/cvtech/persons", String.class)); 使用MockMvcWebTestClient時相同。

對於那些使用 Kotlin 的人來說,使用字段注入意味着必須使用lateinit var字段。 這遠非理想。

但是,可以在 SpringBoot 測試中使用構造函數注入,使用@TestConstructor

@ExtendWith(SpringExtension::class)
@TestConstructor(autowireMode = ALL)
@SpringBootTest(
    classes = [MyApplication::class],
    webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
)
internal class MyIntegrationTest(
    val beanA: BeanA,
    @Qualifier("some qualified") val beanB: BeanB,
) {
...
// Tests can use the beans injected in the constructor without any problems
...
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM