0

当我的 jUnit 测试结束时,我收到以下异常:

7 May 2014 18:06:29  INFO GenericApplicationContext - Closing  org.springframework.context.support.GenericApplicationContext@7b0133c2: startup date [Tue May 27      18:06:09 IDT 2014]; root of context hierarchy
27 May 2014 18:06:29  INFO DefaultLifecycleProcessor - Stopping beans in phase 2147483647
27 May 2014 18:06:29  INFO NettyTcpClient - CLOSED: [id: 0x09b0bb52, /127.0.0.1:56869 :>  /127.0.0.1:61613]
27 May 2014 18:06:31 ERROR StompBrokerRelayMessageHandler - Error while shutting down TCP client
java.util.concurrent.TimeoutException
at org.springframework.messaging.tcp.reactor.AbstractPromiseToListenableFutureAdapter.get(AbstractPromiseToListenableFutureAdapter.java:84)
at org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler.stopInternal(StompBrokerRelayMessageHandler.java:377)
at org.springframework.messaging.simp.broker.AbstractBrokerMessageHandler.stop(AbstractBrokerMessageHandler.java:150)
at org.springframework.messaging.simp.broker.AbstractBrokerMessageHandler.stop(AbstractBrokerMessageHandler.java:164)
at org.springframework.context.support.DefaultLifecycleProcessor.doStop(DefaultLifecycleProcessor.java:229)
at org.springframework.context.support.DefaultLifecycleProcessor.access$300(DefaultLifecycleProcessor.java:51)
at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.stop(DefaultLifecycleProcessor.java:363)
at org.springframework.context.support.DefaultLifecycleProcessor.stopBeans(DefaultLifecycleProcessor.java:202)
at org.springframework.context.support.DefaultLifecycleProcessor.onClose(DefaultLifecycleProcessor.java:118)
at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:888)
at org.springframework.context.support.AbstractApplicationContext$1.run(AbstractApplicationContext.java:809)
27 May 2014 18:06:31  INFO ThreadPoolTaskExecutor - Shutting down ExecutorService 'brokerChannelExecutor'
27 May 2014 18:06:31  INFO ThreadPoolTaskScheduler - Shutting down ExecutorService 'messageBrokerSockJsTaskScheduler'
27 May 2014 18:06:31  INFO ThreadPoolTaskExecutor - Shutting down ExecutorService 'clientOutboundChannelExecutor'
27 May 2014 18:06:31  INFO ThreadPoolTaskExecutor - Shutting down ExecutorService 'clientInboundChannelExecutor'
27 May 2014 18:06:31  INFO EhCacheManagerFactoryBean - Shutting down EhCache CacheManager
27 May 2014 18:06:31  INFO LocalContainerEntityManagerFactoryBean - Closing JPA EntityManagerFactory for persistence unit 'default'
27 May 2014 18:06:31  INFO DefaultContextLoadTimeWeaver - Removing all registered transformers for class loader: sun.misc.Launcher$AppClassLoader

任何想法如何防止这种情况?

PS - 测试成功了,但我真的很讨厌看到堆栈跟踪

编辑 - 我的测试课:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "file:src/main/webapp/WEB-INF/spring/application-context.xml" })
public class EmptyTest{
  /**
  * Test (empty)
  */
  @Test()
  public void emptyTest() {

  assertTrue(true);

  }

}

这是我的代理配置文件:

@Configuration
@EnableWebSocketMessageBroker
@EnableScheduling
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

@Override
public void configureMessageBroker(MessageBrokerRegistry config) {

config.enableStompBrokerRelay(
                  "/topic",
                  "/queue/");

config.setApplicationDestinationPrefixes("/app");
}


@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {

registry.addEndpoint(
             "/wsdemo").withSockJS();
}

}
4

1 回答 1

1

在我看来,您有几个选择,具体取决于您现在想要在测试中实现什么,以及您将来可能希望能够做什么。

1) 如果您的测试根本不需要 websocket 配置,请将其更改为指向不包含WebSocketConfig.

2)如果您的测试需要 websocket 配置,但您不需要代理中继(我不明白为什么在测试中需要它),您可以添加另一个用于测试的配置,registry.enableSimpleBroker("/topic", "/queue/")而不是enableStompBrokerRelay. 然后将没有与代理的 TCP 连接。这种方法的明显缺点是您没有测试您的实际配置,并且您正在复制目标前缀。

3) 为您的测试运行嵌入式 STOMP 代理。我不是 100% 肯定存在这样的事情 - 我知道 ActiveMQ 支持 STOMP 并且支持在 VM 内部运行,但我没有尝试使用 STOMP。如果可能,这种方法的优点是您的测试将测试非常接近真实代码的东西。

4) 您可以自定义 STOMP 代理中继,以使您可以完全控制您的应用程序从代理接收的内容。您可以StompBrokerRelayMessageHandler通过添加扩展的配置类来自定义管理与中继代理的连接DelegatingWebSocketMessageBrokerConfiguration以覆盖该stompBrokerRelayMessageHandler()方法。例如,您可以将它使用的 TCP 客户端设置为您自己的TcpOperations. 下面是一个示例 TCP 客户端,它什么都不做,即让 Handler 认为它已连接,但无法接收或发送消息。

@Override
public AbstractBrokerMessageHandler stompBrokerRelayMessageHandler() {
    AbstractBrokerMessageHandler handler = super.stompBrokerRelayMessageHandler();

    if (handler instanceof StompBrokerRelayMessageHandler) {
        StompBrokerRelayMessageHandler stompHandler = (StompBrokerRelayMessageHandler) handler;
        stompHandler.setTcpClient(new TcpOperations<byte[]>() {
            @Override
            public ListenableFuture<Void> connect(TcpConnectionHandler<byte[]> connectionHandler) {
                return new CompletedListenableFuture<>(null);
            }

            @Override
            public ListenableFuture<Void> connect(TcpConnectionHandler<byte[]> connectionHandler, ReconnectStrategy reconnectStrategy) {
                return new CompletedListenableFuture<>(null);
            }

            @Override
            public ListenableFuture<Void> shutdown() {
                return new CompletedListenableFuture<>(null);
            }
        });
    }

    return handler;
}

请注意,这CompletedListenableFuture只是ListenableFuture在构造后完成的一个实现,并立即addCallback使用传递给构造函数的值调用传递给的任何回调。

这里的重点是您可以轻松自定义代理中继组件的确切行为,以便在测试中更好地控制它们。我不知道有任何内置支持可以使这种测试更容易,但是 websocket 支持仍然很新。我建议你看看 Rossen Stoyanchev 的优秀示例项目spring-websocket-portfolio,如果你还没有这样做的话,因为它包含了几个如何在不同级别测试 websocket 配置的示例(只有一个控制器,加载完整的上下文,运行嵌入式服务器, ...)。希望这也有助于您决定如何测试您的应用程序,以及您可能需要自定义哪些内容。

于 2014-05-28T11:20:25.850 回答