ETJava Beta | Java    注册   登录
  • Springboot单元测试 IllegalStateException

    发表于 2025-02-03 18:25:57     阅读(196)     博客类别:Springboot

    SpringBoot单元测试报IllegalStateException: Failed to load ApplicationContext错误的解决方法

    报错描述

    在使用SpringBootTest单元测试时 出现非法状态异常 
    一直提示无法加载应用上下文 是由于我们使用了WebSocket在测试环境启动时嵌入的Servlet容器导致
    
    报错信息部分内容如下
    java.lang.IllegalStateException: Failed to execute CommandLineRunner
    	at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:787) ~[spring-boot-2.2.8.RELEASE.jar:2.2.8.RELEASE]
    	at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:768) ~[spring-boot-2.2.8.RELEASE.jar:2.2.8.RELEASE]
    	at org.springframework.boot.SpringApplication.run(SpringApplication.java:322) ~[spring-boot-2.2.8.RELEASE.jar:2.2.8.RELEASE]
    	at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:124) [spring-boot-test-2.2.8.RELEASE.jar:2.2.8.RELEASE]
    	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99) [spring-test-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(
    
    java.lang.IllegalStateException: Failed to load ApplicationContext
    	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:132) ~[spring-test-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    	at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:123) ~[spring-test-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    	at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:190) ~[spring-test-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    	at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:132) ~[spring-test-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    	at org.springframework.test.context.TestContextManager.prepareTestInstance
    
    Caused by: java.lang.IllegalStateException: Failed to execute CommandLineRunner
    	at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:787) ~[spring-boot-2.2.8.RELEASE.jar:2.2.8.RELEASE]
    	at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:768) ~[spring-boot-2.2.8.RELEASE.jar:2.2.8.RELEASE]
    	at org.springframework.boot.SpringApplication.run(SpringApplication.java:322) ~[spring-boot-2.2.8.RELEASE.jar:2.2.8.RELEASE]
    	at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:124) ~[spring-boot-test-2.2.8.RELEASE.jar:2.2.8.RELEASE]
    	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99) ~[spring-test-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124) ~[spring-test-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    	... 65 common frames omitted
    Caused by: java.lang.NullPointerException: null
    	at com.etjava.config.StartupRunner.loadData(StartupRunner.java:61) ~[classes/:na]
    	at com.etjava.config.StartupRunner.run(StartupRunner.java:56) ~[classes/:na]
    	at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:784) ~[spring-boot-2.2.8.RELEASE.jar:2.2.8.RELEASE]
    	... 70 common frames omitted
    
    
    java.lang.IllegalStateException: Failed to load ApplicationContext

    解决方案

    将@SpringBootTest的属性webEnvironment改为SpringBootTest.WebEnvironment.RANDOM_PORT即可
    例如:
    @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
    
    
    解释:
    @SpringBootTest的webEnvironment属性默认是MOCK值,它会使用Mock的Servlet环境,而不会启动嵌入式的Servlet容器,这意味着不能进行真实网络请求。当将属性值改为RANDOM_PORT时,它会启动嵌入式的Servlet容器(如Tomcat),并在一个随机端口上监听,这在WebSocket测试是必要的。
    
    WebSocket是一种在单个TCP连接上进行全双工通信的协议。这意味着客户端和服务器之间需要持续的、双向的数据流。在单元测试中,如果使用了Mock的Servlet环境(即webEnvironment = MOCK),则不会启动嵌入式的Servlet容器,因此WebSocket连接无法建立。
    
    而设置webEnvironment = RANDOM_PORT时,Spring Boot会启动一个嵌入式的Servlet容器(如Tomcat),并在一个随机端口上监听。这允许你的测试代码通过WebSocket客户端连接到这个容器,从而进行实际的网络通信测试。这是WebSocket集成测试所必需的。
    
    所以我们只需要将webEnvironment 的webEnvironment属性改SpringBootTest.WebEnvironment.RANDOM_PORT即可