2

I include a websocket to my project and then i have error wherever i use @WebAppConfiguration. So I try to find a problem and get that ServletContext is mocked and not instance of ContextHandler.Context So how can i fix my MVC tests and use websockets in one project?

example of MVC test

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {WebAppConfig.class})
@WebAppConfiguration
public class PlayerControllerTest {

  private MockMvc mockMvc;

  @Mock
  private PlayerService playerService;

  @InjectMocks
  private PlayerController playerController;

  @Test
  public void getById()
  throws Exception {

    when(playerService.find(0L)).thenReturn(region);

    mockMvc.perform(get("/player/{playerId}", 0L))
        .andExpect(status().isOk())
        .andExpect(content().contentType("application/json;charset=UTF-8"))
        .andExpect(jsonPath("playerName").value("Russia"))
        .andExpect(jsonPath("id").value(0));

    verify(playerService, times(1)).find(0L);
    verifyNoMoreInteractions(playerService);
  }

  @Before
  public void setUp() {
    MockitoAnnotations.initMocks(this);
    this.mockMvc = MockMvcBuilders.standaloneSetup(playerController).build();
  }
}

Websocket config

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {

  @Autowired
  ServletContext servletContext;

  @Override
  public void registerStompEndpoints(StompEndpointRegistry registry) {
    registry.addEndpoint("/supportChat")
        .setHandshakeHandler(handshakeHandler())
        .setAllowedOrigins("*")
        .withSockJS().setClientLibraryUrl("//cdn.jsdelivr.net/sockjs/1.1.2/sockjs.min.js");
  }

  @Bean
  public DefaultHandshakeHandler handshakeHandler() {

    WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
    policy.setInputBufferSize(8192);
    policy.setIdleTimeout(TimeUnit.DAYS.toMillis(1000));

    servletContext.setAttribute(DecoratedObjectFactory.ATTR, new DecoratedObjectFactory());
    return new DefaultHandshakeHandler(
        new JettyRequestUpgradeStrategy(new WebSocketServerFactory(servletContext, policy)));
  }

  @Override
  public void configureMessageBroker(MessageBrokerRegistry config) {
    config.enableSimpleBroker("/queue", "/topic");
    config.setApplicationDestinationPrefixes("/app");
  }

  @Override
  protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
    messages.simpDestMatchers("/app/supportChat/**", "/supportChat/**")
        .PermitAll();
  }

  @Override
  protected boolean sameOriginDisabled() {
    return true;
  }

  @Override
  public void configureClientOutboundChannel(ChannelRegistration registration) {
    registration.taskExecutor().corePoolSize(8);
    registration.setInterceptors(presenceChannelInterceptor());
  }

  /**
   * Use for debug of STOMP over WebSocket.
   * @see PresenceChannelInterceptor
   */
  @Bean
  public PresenceChannelInterceptor presenceChannelInterceptor() {
    return new PresenceChannelInterceptor();
  }

  @Override
  protected void customizeClientInboundChannel(final ChannelRegistration registration) {
    registration.setInterceptors(new SubscribeInterceptor());
  }

  @Override
  public boolean configureMessageConverters(List<MessageConverter> messageConverters) {
    messageConverters.add(new GsonMessageConverter());
    return true;
  }
}

Exception

java.lang.IllegalStateException: Failed to load ApplicationContext

    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
    at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
    at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:189)
    at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:131)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: org.springframework.context.ApplicationContextException: Failed to start bean 'stompWebSocketHandlerMapping'; nested exception is java.lang.IllegalStateException: Unable to start Jetty WebSocketServerFactory
    at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:176)
    at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:51)
    at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:346)
    at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:149)
    at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:112)
    at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:879)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:545)
    at org.springframework.test.context.web.AbstractGenericWebContextLoader.loadContext(AbstractGenericWebContextLoader.java:134)
    at org.springframework.test.context.web.AbstractGenericWebContextLoader.loadContext(AbstractGenericWebContextLoader.java:61)
    at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:108)
    at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:251)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
    ... 24 more
   Caused by: java.lang.IllegalStateException: Unable to start Jetty WebSocketServerFactory
    at org.springframework.web.socket.server.jetty.JettyRequestUpgradeStrategy.start(JettyRequestUpgradeStrategy.java:126)
    at org.springframework.web.socket.server.support.AbstractHandshakeHandler.doStart(AbstractHandshakeHandler.java:204)
    at org.springframework.web.socket.server.support.AbstractHandshakeHandler.start(AbstractHandshakeHandler.java:198)
    at org.springframework.web.socket.sockjs.transport.handler.WebSocketTransportHandler.start(WebSocketTransportHandler.java:91)
    at org.springframework.web.socket.sockjs.transport.TransportHandlingSockJsService.start(TransportHandlingSockJsService.java:163)
    at org.springframework.web.socket.sockjs.support.SockJsHttpRequestHandler.start(SockJsHttpRequestHandler.java:103)
    at org.springframework.web.socket.server.support.WebSocketHandlerMapping.start(WebSocketHandlerMapping.java:65)
    at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:173)
    ... 36 more
Caused by: java.lang.NullPointerException
    at org.eclipse.jetty.websocket.server.WebSocketServerFactory.doStart(WebSocketServerFactory.java:320)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at org.springframework.web.socket.server.jetty.JettyRequestUpgradeStrategy$ModernJettyWebSocketServerFactoryAdapter.startFactory(JettyRequestUpgradeStrategy.java:303)
    at org.springframework.web.socket.server.jetty.JettyRequestUpgradeStrategy$WebSocketServerFactoryAdapter.start(JettyRequestUpgradeStrategy.java:276)
    at org.springframework.web.socket.server.jetty.JettyRequestUpgradeStrategy.start(JettyRequestUpgradeStrategy.java:123)
    ... 43 more
1
  • Try specifying webenvironment to use a random port. Something like this .@SpringBootTest(classes = TestApp.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) Commented May 31, 2018 at 9:25

1 Answer 1

2

I too faced a similar issue
The problem was with the web application context using a mocked port which failed to create required beans for jetty to operate.

For a spring boot application Try annotating

@SpringBootTest(classes = TestApp.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)

against your test class. By default web environment uses a mocked port

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.