Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SpringBootTest @EnabledWebSocket ignored

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?

like image 643
CPA Avatar asked Feb 04 '26 17:02

CPA


2 Answers

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));
like image 51
CPA Avatar answered Feb 07 '26 05:02

CPA


In my case, adding @EnableAutoConfiguration on my Spring boot test class, resolve this issue. Spring initialize DispatcherServlet and properly config it

like image 35
Vlad Cheremisin Avatar answered Feb 07 '26 05:02

Vlad Cheremisin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!