I am using Redis Server for message broker in my spring boot application.
Is there any simple way to Junit my publish and receive API?
e.g :
Publisher :
public String publish(Object domainObj) {
template.convertAndSend(topic.getTopic(), domainObj.toString());
return "Event Published";
}
Receiver :
public class Receiver implements MessageListener {
@Override
public void onMessage(Message message, byte[] bytes) {
System.out.println("Consumed Message {}" + message);
}
}
I am using JedisConnectionFactory
and RedisMessageListenerContainer
and RedisTemplate
for my implementation
@Configuration
@EnableRedisRepositories
public class RedisConfig {
@Bean
public JedisConnectionFactory connectionFactory() {
RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
configuration.setHostName("localhost");
configuration.setPort(6379);
return new JedisConnectionFactory(configuration);
}
@Bean
public RedisTemplate<String, Object> template() {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory());
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new JdkSerializationRedisSerializer());
template.setValueSerializer(new JdkSerializationRedisSerializer());
template.setEnableTransactionSupport(true);
template.afterPropertiesSet();
return template;
}
@Bean
public ChannelTopic topic() {
return new ChannelTopic("common-channel");
}
@Bean
public MessageListenerAdapter messageListenerAdapter() {
return new MessageListenerAdapter(new Receiver());
}
@Bean
public RedisMessageListenerContainer redisMessageListenerContainer() {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory());
container.addMessageListener(messageListenerAdapter(), topic());
return container;
}
2
Answers
The simplest way to unit test this is to use
embedded-redis
module. What you do is inBeforeAll
you can start embedded Redis and stop the embedded Redis inAfterAll
method.You can also
PostConstruct
PreDestroy
annotations to accomplish this.If you’re looking for Junit5 then you can find the code in my repo here
See BootstrapRedis annotation and their usage here
https://github.com/sonus21/rqueue/blob/7ef545c15985ef91ba719f070f7cc80745525047/rqueue-core/src/test/java/com/github/sonus21/rqueue/core/RedisScriptFactoryTest.java#L40
Unit Testing Receiver and Publisher implementation is quite straight.
JUnit 5 coupled with Mockito extension should do the job.
For example for testing that :
I expect that
topic
andtemplate
be fields of the current class.These fields could be set by constructor.
So you could write something that check that
convertAndSend()
is eventually executed with the correct parameters :But I don’t think that the unit test of these two classes be enough because it never tests the final things : the JMS processing performed by Redis backend.
Particularly, the
RedisConfig
part that you set with specific things as serializers that have important side effects on the processing.For my part, I try to always write integration or partial integration tests for Redis backend stuffs to ensure a good no regression harness.
The java embedded-redis library is good for that. It allows to start a redis server
on localhost (works on Windows as well as on Linux).
Starting and stopping the redis server is as simple as :
Move the
start()
in the@BeforeEach
and thestop()
in the@AfterEach
and the server is ready.Then it still requires some adjustments to ensure that the redis configuration specified in Spring is well setup during the tests while using your local redis server and not the "real" redis server. Not always simple to set but great when it is done !