I have simple web application:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@RestController
public class SimpleController {
@Autowired
private String sayHello;
@GetMapping("/hello")
public String hello() {
return sayHello;
}
}
@Configuration
public class StringConfig {
@Bean
public String sayHelloWorld() {
return "Hello, World!";
}
}
And add tests:
//This is abstarct class for test.
@WebAppConfiguration
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = Application.class)
public abstract class AbstractTestClass {
@Autowired
private WebApplicationContext webApplicationContext;
protected MockMvc mockMvc;
@Before
public void init() {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
}
//This is custom configuration for bean "sayHello".
@Configuration
public class ConfigurationForTest {
@Bean
public String sayHello() {
return "Hello, Test1!";
}
}
//This test loads custom config with ApplicationContext.
@ContextConfiguration(classes = ConfigurationForTest.class)
public class SimpleControllerTest1 extends AbstractTestClass {
//Checks that enpoind return expected reponse.
@Test
public void shouldReturnHelloTest1() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/hello"))
.andExpect(MockMvcResultMatchers.content().string("Hello, Test1!"));
}
}
//This test don't loads custom configuration and works on default ApplicationContext.
public class SimpleControllerTest2 extends AbstractTestClass {
//Checks that enpoind return expected reponse.
@Test
public void shouldReturnHelloWorld() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/hello"))
.andExpect(MockMvcResultMatchers.content()
.string("Hello,World!"));
}
}
This test fails with:
Failed to load ApplicationContext
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.jmx.export.UnableToRegisterMBeanException: Unable to register MBean [org.springframework.cloud.context.environment.EnvironmentManager@1ed864e4] with key 'environmentManager'; nested exception is javax.management.InstanceAlreadyExistsException: org.springframework.cloud.context.environment:name=environmentManager,type=EnvironmentManager
Caused by: javax.management.InstanceAlreadyExistsException: org.springframework.cloud.context.environment:name=environmentManager,type=EnvironmentManager
What is it caused by? It isn't clear for me. I know that i can add @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
or use other annotation @WebMvcTest
, @SpringBootTest + @AutoConfigureMockMvc
.
But I want to know why is it happend and and how to load the whole application context dirrectly using this approach if my application will be more complex?
What is the difference between @ContextConfiguration(classes=Application.class)
and @SpringBootTest
. Why does this error not occur when i use @SpringBootTest
? With @SpringBootTest
ApplciationContext is loaded twice too, but tests pass successfully.