Spring-boot Redis JMS JUnit

问题描述

我在 Spring Boot 应用程序中使用 Redis 服务器作为消息代理。 有没有什么简单的方法可以对我的发布和接收 API 进行 Junit?

例如:

出版商:

public String publish(Object domainObj) {

    template.convertAndSend(topic.getTopic(),domainObj.toString());
    return "Event Published";
}

接收方:

公共类Receiver实现MessageListener{

@Override
public void onMessage(Message message,byte[] bytes) {

    System.out.println("Consumed Message {}" + message);

}

}

我正在使用 JedisConnectionFactoryRedisMessageListenerContainer 以及 Redistemplate 进行我的实现

@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;
    }

解决方法

单元测试接收器和发布器的实现非常简单。
JUnit 5 加上 Mockito 扩展应该可以完成这项工作。

例如用于测试:

public String publish(Object domainObj) {
    template.convertAndSend(topic.getTopic(),domainObj.toString());
    return "Event Published";
}

我希望 topictemplate 是当前类的字段。 这些字段可以由构造函数设置。

所以你可以写一些东西来检查 convertAndSend() 最终是否使用正确的参数执行:

@Mock 
RedisTemplate<String,Object> templateMock;

@Test
void publish(){
   Topic topicFixture = new Topic(...);
   Object domainObjFixture = new FooBar(...);
   Publisher publisher = new Publisher(templateMock,topicFixture);
   //when
   publisher.publish(domainObjFixture);
   // then
   Mockito.verify(templateMock)
          .convertAndSend(topicFixture.getTopic(),domainObjFixture);      
}

但是我认为这两个类的单元测试还不够,因为它从来没有测试过最后的东西:Redis 后端执行的 JMS 处理。
特别是,您将特定事物设置为对处理具有重要副作用的序列化程序的 RedisConfig 部分。
就我而言,我总是尝试为 Redis 后端编写集成或部分集成测试,以确保良好的无回归工具。

java embedded-redis library 对此很有用。它允许启动一个 redis 服务器 在本地主机上(适用于 Windows 和 Linux)。
启动和停止 redis 服务器就这么简单:

RedisServer redisServer = new RedisServer(6379);
redisServer.start();
// do some work
redisServer.stop();

移动 start() 中的 @BeforeEachstop() 中的 @AfterEach,服务器就准备好了。
然后它仍然需要一些调整以确保在使用本地 redis 服务器而不是“真实”redis 服务器的测试期间,Spring 中指定的 redis 配置设置良好。设置并不总是简单,但完成后很棒!

,

进行单元测试的最简单方法是使用 embedded-redis 模块。您所做的是在 BeforeAll 中您可以启动嵌入式 Redis 并在 AfterAll 方法中停止嵌入式 Redis。

您还可以通过 PostConstruct PreDestroy 批注来完成此操作。

如果您正在寻找 Junit5,那么您可以在我的 repo 中找到代码

在此处查看 BootstrapRedis 注释及其用法

https://github.com/sonus21/rqueue/blob/7ef545c15985ef91ba719f070f7cc80745525047/rqueue-core/src/test/java/com/github/sonus21/rqueue/core/RedisScriptFactoryTest.java#L40