Reputation: 6532
I am getting the following exception when my jUnit test is ending:
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
Any ideas how to prevent that?
P.S - The tests are succeeding but I really hate to see that stack trace
EDIT - my test class:
@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);
}
}
And here is my config file for the broker:
@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();
}
}
Upvotes: 0
Views: 2481
Reputation: 13907
As I see it, you have a few options, depending on exactly what you want to achieve in your tests now, and what you might want to be able to do in the future.
1) If your test does not need the websocket configuration at all, change it to point at a custom context configuration that does not include the WebSocketConfig
.
2) If your test needs the websocket config, but you don't need the broker relay (I can't see why it would be required in a test), you could add another Configuration for testing that uses registry.enableSimpleBroker("/topic", "/queue/")
instead of enableStompBrokerRelay
. Then there will be no TCP connection to the broker. The obvious disadvantage with this approach is that you are not testing your actual config, and that you are duplicating the destination prefixes.
3) Run an embedded STOMP broker for your tests. I'm not 100% certain such a thing exists - I know ActiveMQ has STOMP support and some support for running inside a VM, but I haven't tried this with STOMP. If possible, the advantage of this approach is that your tests would be testing something very close to the real code.
4) You could customise the STOMP broker relay to such an extent that you have full control over what your application receives from the broker. You can customise the StompBrokerRelayMessageHandler
which manages the connection to the relay broker by adding a Configuration class that extends DelegatingWebSocketMessageBrokerConfiguration
in order to override the stompBrokerRelayMessageHandler()
method. For example, you can set the TCP client it uses to your own implementation of TcpOperations
. Below is an example TCP client that simply does nothing, i.e. makes the Handler think it is connected, but cannot receive or send messages.
@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;
}
Note that CompletedListenableFuture
is just an implementation of ListenableFuture
that is done after construction, and immediately calls any callbacks passed to addCallback
with the value passed into the constructor.
The point here is that you can easily customise the exact behaviour of the broker relay components, so you can control them better in your tests. I am not aware of any built-in support to make this kind of testing easier, but then again the websocket support is still pretty new. I would suggest that you look at Rossen Stoyanchev's excellent example project spring-websocket-portfolio
, if you haven't done so already, as it includes several examples of how to test the websocket configuration at different levels (just one controller, loading the full context, running an embedded server, ...). Hopefully this is also helpful for deciding how you want to test your application, and what you might need to customise to do it.
Upvotes: 1