Reputation: 3908
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?
Upvotes: 6
Views: 9085
Reputation: 40048
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.
Upvotes: 7
Reputation: 121
Define all properties in src/test/resource/application.file example to use junit 5 for rest layer:
@ExtendWith(MockitoExtension.class)
public class RestTest {
@InjectMocks
private RestClass restClass;
private MockMvc mockMvc;
@BeforeEach
public void init() throws Exception {
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders.standaloneSetup(restClass).build();
}
@Test
public void test() throws Exception {
String url = "/url";
ResultActions resultActions = mockMvc.perform(get(url));
resultActions.andExpect(status().isOk());
}
}
Upvotes: 0