当前位置: 首页 > 工具软件 > X.org Server > 使用案例 >

SpringBoot启动单元测试报错javax.websocket.server.ServerContainer not available

翟丰茂
2023-12-01

在运行SpringBoot单元测试时,出现以下报错

Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'serverEndpointExporter' defined in class path resource [XXX/XXX/WebSocketConfig.class]: Invocation of init method failed;
nested exception is java.lang.IllegalStateException: javax.websocket.server.ServerContainer not available

导致启动单元测试失败,遇到这类错误,要从末尾往前看,往往末尾的一个报错是根本原因。

这里可以看到是因为javax.websocket.server.ServerContainer不可用,抛出了一个IllegalStateException。

很明显它是一个websocket包下的类,那么应该就和websocket拖不了干系。

通过查阅资料得知,这是因为在启动单元测试时,SpringBootTest不会启动服务器,WebSocket自然也就没有启动,但是在代码里又配置了WebSocket,就会出错。

解决方法:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)

在SprintBootTest里加上一段配置,指定一个Web环境,值为随机端口。

解析:

点进SpringBootTest的注解可以看到这样一段代码:

    /**
	 * The type of web environment to create when applicable. Defaults to
	 * {@link WebEnvironment#MOCK}.
	 * @return the type of web environment
	 */
	WebEnvironment webEnvironment() default WebEnvironment.MOCK;

可以得知这个webEnvironment是指明运行时创建的web环境。

关于WebEnvironment这个类的定义在下面:

    /**
	 * An enumeration web environment modes.
	 */
	enum WebEnvironment {

		/**
		 * Creates a {@link WebApplicationContext} with a mock servlet environment if
		 * servlet APIs are on the classpath, a {@link ReactiveWebApplicationContext} if
		 * Spring WebFlux is on the classpath or a regular {@link ApplicationContext}
		 * otherwise.
		 */
		MOCK(false),

		/**
		 * Creates a web application context (reactive or servlet based) and sets a
		 * {@code server.port=0} {@link Environment} property (which usually triggers
		 * listening on a random port). Often used in conjunction with a
		 * {@link LocalServerPort} injected field on the test.
		 */
		RANDOM_PORT(true),

		/**
		 * Creates a (reactive) web application context without defining any
		 * {@code server.port=0} {@link Environment} property.
		 */
		DEFINED_PORT(true),

		/**
		 * Creates an {@link ApplicationContext} and sets
		 * {@link SpringApplication#setWebApplicationType(WebApplicationType)} to
		 * {@link WebApplicationType#NONE}.
		 */
		NONE(false);

		private final boolean embedded;

		WebEnvironment(boolean embedded) {
			this.embedded = embedded;
		}

		/**
		 * Return if the environment uses an {@link ServletWebServerApplicationContext}.
		 * @return if an {@link ServletWebServerApplicationContext} is used.
		 */
		public boolean isEmbedded() {
			return this.embedded;
		}

	}

这是一个内部枚举类,包含了四个值:MOCK、RANDOM_PORT、DEFINED_PORT和NONE,我们这里使用RANDOM_PORT枚举值随机端口,MOCK代表你配置文件里指明的端口,DEFINED_PORT代表你可以设置端口号。

如果您觉得文章写得还不错,不妨点个赞。如果有什么疑惑或者不对的地方,可以留下评论,看到我会及时回复的。所有关注都会回关!

 类似资料: