问题描述
我有一个简单的健康控制器,定义如下:
@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
SpringBootTest : Spring boot test annotation actual load the application context for test environment
这篇关于Spring Boot @WebMvcTest 与 @SpringBootTest的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!