I want to test my WebSocket application.
The test class:
@RunWith(SpringRunner.class)
@SpringBootTest(
webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@ContextConfiguration(
classes = {WebConfig.class, WebSocketConfig.class}
@DirtiesContext
public class IntegrationTest {
@Autowired
public EmbeddedWebApplicationContext server;
@Test
...
}
The WebConfig class:
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
public final WebSocketService webSocketService;
@Autowired
public WebConfig(WebSocketService webSocketService) {
this.webSocketService = webSocketService;
}
@Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
tomcat.setPort(1234);
tomcat.setContextPath("/test");
return tomcat;
}
}
And the WebSocketConfig class:
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Autowired
public WebSocketConfig() {}
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
webSocketHandlerRegistry.addHandler(webSocketHandler(), "ws")
.setAllowedOrigins("*")
}
@Bean
public WebSocketHandler webSocketHandler() {
return new WebsocketHandler(webSocketService());
}
@Bean
publicWebSocketService webSocketService() {
return newWebSocketServiceImpl();
}
}
When I start the test, Tomcat is starting and is listening at the specified Port 1234. But I can't connect a websocket client. The WebSocketConfig is called. But I think the websocket mapping doesn't work. Did I forget anything to configure?
When I am starting the test with the application class (WebSocketApp.class) which is annotated with @SpringBootApplication, then the websocket mapping works fine.
@RunWith(SpringRunner.class)
@SpringBootTest(
webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@ContextConfiguration(
classes = {WebSocketApp.class}
@DirtiesContext
public class IntegrationTest {
@Autowired
public EmbeddedWebApplicationContext server;
@Test
...
}
The WebSocketApp also uses the same configurations.
I assume the second approach is working, because the @EnableWebSocket is used. And when I don't take the WebSocketApp.class (annotated with @SpringBootApplication) the @EnableWebSocket will be ignored.
Does anybody have an idea to get the test running? How can I enable websockets manually without annotations?
EDIT:
I found out, that there the TomcatEmbeddedContext is using a default servlet mapping instead a dispatcherServlet mapping. Is it possible to set this type of mapping?
I found a solution. In test configuration Spring didn't bootstrap the websocket container and the servlet mapping.
I had to add some additional configurations:
@Bean
public ServletServerContainerFactoryBean createWebSocketContainer() {
ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
container.setMaxTextMessageBufferSize(8192);
container.setMaxBinaryMessageBufferSize(8192);
return container;
}
@Bean
public DispatcherServlet dispatcherServlet() {
return new DispatcherServlet();
}
@Bean
public ServletRegistrationBean dispatchServletRegistration() {
ServletRegistrationBean registration = new ServletRegistrationBean(
dispatcherServlet(), "/");
registration
.setName(DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);
return registration;
}
And to EmbeddedServletContainerFactory bean:
tomcat.addContextCustomizers((TomcatContextCustomizer) context ->
context.addServletContainerInitializer(new WsSci(), null));
In my case, adding @EnableAutoConfiguration on my Spring boot test class, resolve this issue. Spring initialize DispatcherServlet and properly config it
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With