Spring Boot @WebMvcTest 与 @SpringBootTest [英] Spring Boot @WebMvcTest vs @SpringBootTest

查看:29
本文介绍了Spring Boot @WebMvcTest 与 @SpringBootTest的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的健康控制器,定义如下:

@RestController@RequestMapping("/admin")公共类 AdminController {@Value("${spring.application.name}")字符串服务名称;@GetMapping("/health")字符串 getHealth() {返回服务名称 + "启动并运行";}}

以及测试它的测试类:

@WebMvcTest(RedisController.class)类 AdminControllerTest {@自动连线私有 MockMvc mockMvc;@测试public void healthShouldReturnDefaultMessage() 抛出异常 {this.mockMvc.perform(get("/admin/health")).andDo(print()).andExpect(status().isOk()).andExpect(content().string(containsString(live-data-service up and running")));}}

运行测试时,我收到以下错误:

***************************应用程序无法启动****************************说明:com.XXXX.LiveDataServiceApplication 中的字段配置需要一个无法找到的com.XXXXX.AppConfiguration"类型的 bean.注入点有以下注释:- @org.springframework.beans.factory.annotation.Autowired(required=true)行动:考虑在您的配置中定义一个com.XXXX.AppConfiguration"类型的 bean.

这里是 AppConfiguration.java 定义在与主 Spring Boot 应用程序类相同的包中:

@Configuration@EnableConfigurationProperties@配置属性公共类 AppConfiguration {@Value("${redis.host}")私有字符串 redisHost;@Value("${redis.port}")私有 int redisPort;@Value("${redis.password:}")私有字符串 redisPassword;...//getter 和 setter 来到这里

主类:

@SpringBootApplication公共类 LiveDataServiceApplication {@自动连线私有 AppConfiguration 配置;公共静态无效主(字符串 [] args){SpringApplication.run(LiveDataServiceApplication.class, args);}@豆公共RedisConnectionFactory redisConnectionFactory() {RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration(configuration.getRedisHost(), configuration.getRedisPort());redisConfiguration.setPassword(configuration.getRedisPassword());返回新的生菜连接工厂(redisConfiguration);}}

如果我修改测试类中的注解如下,测试通过:

@SpringBootTest@AutoConfigureMockMvc类 AdminControllerTest {....

我错过了什么?

解决方案

@WebMvcTest@SpringBootTest

的用法你应该明白

@WebMvcTest : 注解只是实例化 web 层而不是整个上下文,所以控制器类中的所有依赖都应该被模拟,你可以看看 文档

<块引用>

Spring Boot 仅实例化 web 层而不是整个上下文.在具有多个控制器的应用程序中,您甚至可以使用例如 @WebMvcTest(HomeController.class).

要求仅实例化一个控制器

<块引用>

我们使用@MockBean 为 GreetingService 创建和注入一个模拟(如果你不这样做,应用程序上下文将无法启动)

SpringBootTest : Spring Boot 测试注解实际加载测试环境的应用上下文

<块引用>

@SpringBootTest 注释告诉 Spring Boot 寻找一个主要的配置类(例如一个带有 @SpringBootApplication 的类)并使用它来启动一个 Spring 应用程序上下文.

I have a simple health controller defined as follows:

@RestController
@RequestMapping("/admin")
public class AdminController {

    @Value("${spring.application.name}")
    String serviceName;

    @GetMapping("/health")
    String getHealth() {
        return serviceName + " up and running";
    }
}

And the test class to test it:

@WebMvcTest(RedisController.class)
class AdminControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void healthShouldReturnDefaultMessage() throws Exception {
        this.mockMvc.perform(get("/admin/health"))
                .andDo(print())
                .andExpect(status().isOk())
                .andExpect(content().string(containsString("live-data-service up and running")));
    }
}

When running the test, I'm getting the below error:

***************************
APPLICATION FAILED TO START
***************************

Description:

Field configuration in com.XXXX.LiveDataServiceApplication required a bean of type 'com.XXXXX.AppConfiguration' that could not be found.

The injection point has the following annotations:
    - @org.springframework.beans.factory.annotation.Autowired(required=true)


Action:

Consider defining a bean of type 'com.XXXX.AppConfiguration' in your configuration.

Here is AppConfiguration.java defined in the same package as the main spring boot app class:

@Configuration
@EnableConfigurationProperties
@ConfigurationProperties
public class AppConfiguration {

    @Value("${redis.host}")
    private String redisHost;

    @Value("${redis.port}")
    private int redisPort;

    @Value("${redis.password:}")
    private String redisPassword;
...
// getters and setters come here

Main class:

@SpringBootApplication
public class LiveDataServiceApplication {

    @Autowired
    private AppConfiguration configuration;

    public static void main(String[] args) {
        SpringApplication.run(LiveDataServiceApplication.class, args);
    }

    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration(configuration.getRedisHost(), configuration.getRedisPort());
        redisConfiguration.setPassword(configuration.getRedisPassword());
        return new LettuceConnectionFactory(redisConfiguration);
    }
}

If I modify the annotation in the test class as follows, the test pass:

@SpringBootTest
@AutoConfigureMockMvc
class AdminControllerTest {
....

What am I missing?

解决方案

You should understand the usage of @WebMvcTest and @SpringBootTest

@WebMvcTest : annotation is only to instantiates only the web layer rather than the whole context, so all dependencies in controller class should be mocked, you can look at the documentation

Spring Boot instantiates only the web layer rather than the whole context. In an application with multiple controllers, you can even ask for only one to be instantiated by using, for example, @WebMvcTest(HomeController.class).

We use @MockBean to create and inject a mock for the GreetingService (if you do not do so, the application context cannot start)

SpringBootTest : Spring boot test annotation actual load the application context for test environment

The @SpringBootTest annotation tells Spring Boot to look for a main configuration class (one with @SpringBootApplication, for instance) and use that to start a Spring application context.

这篇关于Spring Boot @WebMvcTest 与 @SpringBootTest的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆