尝试在普通 Spring 测试中启动 Spring Boot 应用程序时 EnvironmentManager 的 InstanceAlreadyExistsException

Sta*_*iuk 5 java spring spring-test spring-test-mvc spring-boot

我有一个简单的网络应用程序:

@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!";
   }
}
Run Code Online (Sandbox Code Playgroud)

并添加测试:

 //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!"));
   }
}
Run Code Online (Sandbox Code Playgroud)

此测试失败:

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

它是由什么引起的?我不清楚。我知道我可以添加@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)或使用其他注释@WebMvcTest, @SpringBootTest + @AutoConfigureMockMvc. 但是我想知道为什么会发生这种情况,以及如果我的应用程序会更复杂,如何使用这种方法直接加载整个应用程序上下文?

是什么区别@ContextConfiguration(classes=Application.class)@SpringBootTest。为什么我使用时不会出现这个错误@SpringBootTest?随着 @SpringBootTestApplciationContext被加载两次了,但是测试顺利通过。