SpringBoot应用程序中的@RabbitListener方法测试

2023-12-26

Code:

RabbitMQ 监听器:

@Component
public class ServerThroughRabbitMQ implements ServerThroughAMQPBroker {
    private static final AtomicLong ID_COUNTER=new AtomicLong();
    private final long instanceId=ID_COUNTER.incrementAndGet();


    @Autowired
    public ServerThroughRabbitMQ( UserService userService,LoginService loginService....){
....
    }

    @Override
    @RabbitListener(queues = "#{registerQueue.name}")
    public String registerUserAndLogin(String json) {
       .....
    }

服务器配置:

@Configuration
public class ServerConfig {
    @Value("${amqp.broker.exchange-name}")
    private String exchangeName;
    @Value("${amqp.broker.host}")
    private String ampqBrokerHost;
    @Value("${amqp.broker.quidco.queue.postfix}")
    private String quidcoQueuePostfix;
    @Value("${amqp.broker.quidco.queue.durability:true}")
    private boolean quidcoQueueDurability;
    @Value("${amqp.broker.quidco.queue.autodelete:false}")
    private boolean quidcoQueueAutodelete;

    private String registerAndLoginQuequName;


    @PostConstruct
    public void init() {
        registerAndLoginQuequName = REGISTER_AND_LOGIN_ROUTING_KEY + quidcoQueuePostfix;
    public String getRegisterAndLoginQueueName() {
        return registerAndLoginQuequName;
    }

    public String getLoginAndCheckBonusQueueName() {
        return loginAndCheckBonusQuequName;
    }



    @Bean
    public ConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory(ampqBrokerHost);
        return connectionFactory;
    }

    @Bean
    public AmqpAdmin amqpAdmin() {
        return new RabbitAdmin(connectionFactory());
    }

    @Bean
    public TopicExchange topic() {
        return new TopicExchange(exchangeName);
    }

    @Bean(name = "registerQueue")
    public Queue registerQueue() {
        return new Queue(registerAndLoginQuequName, quidcoQueueDurability, false, quidcoQueueAutodelete);
    }


    @Bean
    public Binding bindingRegisterAndLogin() {
        return BindingBuilder.bind(registerQueue()).to(topic()).with(REGISTER_AND_LOGIN_ROUTING_KEY);
    }

   }

测试配置:

@EnableRabbit
@TestPropertySource("classpath:test.properties")
public class ServerThroughAMQPBrokerRabbitMQIntegrationTestConfig {
    private final ExecutorService=Executors.newCachedThreadPool();
    private LoginService loginServiceMock=mock(LoginService.class);
    private UserService userServiceMock =mock(UserService.class);

    @Bean
    public ExecutorService executor() {
        return executorService;
    }

    @Bean
    public LoginService getLoginServiceMock() {
        return loginServiceMock;
    }

    @Bean
    public UserService getUserService() {
        return userServiceMock;
    }

    @Bean
    @Autowired
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setMaxConcurrentConsumers(5);
        return factory;
    }

    @Bean
    @Autowired
    public RabbitTemplate getRabbitTemplate(ConnectionFactory connectionFactory) {
        final RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        return rabbitTemplate;
    }

    @Bean
    public ServerThroughRabbitMQ getServerThroughRabbitMQ() {
        return new ServerThroughRabbitMQ(userServiceMock, loginServiceMock,...);
    }

}

集成测试:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes ={ServerConfig.class,ServerThroughAMQPBrokerRabbitMQIntegrationTestConfig.class})
@Category({IntegrationTest.class})
@TestPropertySource("classpath:test.properties")
public class ServerThroughAMQPBrokerRabbitMQIntegrationTest {
    final private ObjectMapper jackson = new ObjectMapper();
    @Autowired
    private ExecutorService executor;

    @Autowired
    private ServerThroughRabbitMQ serverThroughRabbitMQ;

    @Autowired
    private RabbitTemplate template;

    @Autowired
    private TopicExchange exchange;

    @Autowired
    UserService userService;

    @Autowired
    LoginService loginService;

    @Autowired
    private AmqpAdmin amqpAdmin;

    @Autowired
    private ServerConfig serverConfig;

    final String username = "username";
    final String email = "[email protected] /cdn-cgi/l/email-protection";
    final Integer tcVersion=1;
    final int quidcoUserId = 1;
    final String jwt = ProcessLauncherForJwtPhpBuilderUnitWithCxtTest.EXPECTED_JWT;


    @Before
    public void cleanAfterOthersForMyself() {
        cleanTestQueues();
    }

    @After
    public void cleanAfterMyselfForOthers() {
        cleanTestQueues();
    }

    private void cleanTestQueues() {
        amqpAdmin.purgeQueue(serverConfig.getRegisterAndLoginQueueName(), false);
    }

    @Test
    @Category({SlowTest.class,IntegrationTest.class})
    public void testRegistrationAndLogin() throws TimeoutException {
        final Waiter waiter = new Waiter();

        when(userService.register(anyString(), anyString(), anyString())).thenReturn(...);
        when(loginService....()).thenReturn(...);


        executor.submit(() -> {
            final RegistrationRequest request = new RegistrationRequest(username, email,tcVersion);
            final String response;
            try {
                //@todo: converter to convert RegistrationRequest inside next method to json
                response = (String) template.convertSendAndReceive(exchange.getName(), REGISTER_AND_LOGIN_ROUTING_KEY.toString(), jackson.writeValueAsString(request));
                waiter.assertThat(response, not(isEmptyString()));

                final RegistrationResponse registrationResponse = jackson.readValue(response, RegistrationResponse.class);
                waiter.assertThat(...);
                waiter.assertThat(...);

            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            waiter.resume();
        });

        waiter.await(5, TimeUnit.SECONDS);
    }

}

当我单独运行该测试时,一切正常,但是当我与其他测试一起运行它时,没有使用通过 RabbitMQ 模拟的服务器,因此一些 spring 缓存强制使用旧的兔子侦听器。

我尝试调试它,我可以看到,正确的 bean 正在自动连接到测试,但由于某种原因,旧侦听器正在使用(旧 bean 字段 instanceId=1 新模拟 bean instanceId=3)并且测试失败(不确定它是如何发生的)可能的,所以如果在现有的旧bean的情况下我假设会得到一个自动装配异常)。

我尝试在 BEFORE_CLASS 之前使用 @DirtiesContext,但遇到了另一个问题(请参阅here https://stackoverflow.com/questions/33993942/spring-boot-test-with-dirtiescontext-before-class)


RabbitMQ 和集成测试可能很困难,因为 Rabbit MQ 保留某种状态: - 队列中先前测试的消息 - 之前测试中的监听器仍在队列上监听

有几种方法:

  • 在开始测试之前清除所有队列(这可能就是您的意思cleanTestQueues())
  • 删除所有队列(或使用临时队列)并在每次测试之前重新创建它们
  • 使用 Rabbit Admin Rest API 终止先前测试的侦听器或连接
  • 删除幽灵并为每个测试重新创建基础设施(这是最残酷的方式)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SpringBoot应用程序中的@RabbitListener方法测试 的相关文章

随机推荐

  • Chrome 标签在前台长时间处于后台后崩溃/挂起

    我有一个显示实时统计数据的页面 它运行大量 JavaScript 发出大量 HTTP 请求 使用 D3 js 每隔几秒渲染一次 SVG 图表 具有大量 CSS 动画 并频繁重新排列 DOM 只要页面聚焦 它就可以顺利运行 如果我切换到另一个
  • 根据条件更改 GridView 行颜色

    我想根据某些条件更改 gridview 的特定行颜色 我正在使用 ASP NET 和 C protected void GridView1 RowDataBound object sender GridViewRowEventArgs e
  • Python内部排序方法[重复]

    这个问题在这里已经有答案了 有谁知道Python在list sort 内部使用什么类型的排序 或者它至少保证 O n log n 这docs http docs python org 2 tutorial datastructures ht
  • 具有重复键名称的 JSON 在解析时会丢失信息

    因此 要么我回去告诉某人他们应该修复 JSON 要么我需要找出我做错了什么 这是 JSON 请注意范围出现三次 String j jobname test parameters parameter name maxErrors value
  • 通过引用 id 分配给环境(即不将 env. 传递给子函数)

    程序员经常在大函数中使用多个小函数 一路上我们可能想要收集某个环境中的东西以供以后参考 我们可以创造一个环境new env hash FALSE 并将其传递给较小的函数并分配assign 好吧 花花公子 我想知道我们是否可以使用环境的引用
  • 更改 dsym 文件中的 uuid

    我一直在努力改变uuid生成的 dsym 文件 以便 crashlytics 可以将崩溃日志与dsym 你知道有什么方法可以做到吗 有关更多上下文 在构建期间上传 dsym 的脚本失败 我没有注意到 Bitcode 被禁用 因此 itune
  • 如何在 Android 中以编程方式在 EditText 中设置 Id

    我在 GridLayout 上有一个名为 addnewTask 的按钮 当您创建此按钮时 它将创建一个 EditText private GridLayout gridLayout int rowIndex 3 int colIndex 1
  • Postgres 将所有数组值与条件 ---updated 匹配到同一列

    我有表 table a 和以下列 id event id 1 101 1 102 1 103 2 105 2 103 2 106 I 和 to 搜索 101 103 使用 and 条件类似于使用 OR 条件进行 IN 查询 例如 id 1
  • 在开发工具时间轴中,空的绿色矩形是什么?

    在 Chrome 开发工具时间轴中 填充的绿色矩形 代表绘制操作 和空的绿色矩形 显然也代表有关绘制操作的某些内容 之间有什么区别 绘画实际上是两个任务 绘制调用和光栅化 绘制调用 这是您想要绘制的内容的列表 它源自应用于您的元素的 CSS
  • 使用减号而不是方括号来格式化美元的负数 (Java)

    如何得到NumberFormat getCurrencyInstance 用减号打印负的美元货币值 它需要对返回的 DecimalFormat 进行一些调整NumberFormat getCurrencyInstance 以独立于语言环境的
  • 在syncfusion柱形图系列中使用隐藏字段

    我在 ASP NET MVC 中使用syncfusion来让我的应用程序显示图表 并且做得很好 现在我必须为每个轴上生成的每个图表设置隐藏字段 并希望在图表的单击函数调用上获取该隐藏字段的值 控制器 public ActionResult
  • 如何在 angularjs 中限制 $http 请求?

    我正在使用 angularjs 为数据导入器构建 UI 角度应用程序将处理输入数据源 电子表格或其他 并将 GET POST 发送到 API 以在服务器上创建 更新记录并检索更改等 如果用户要导入数千条记录 我可能不想一次打开数千个 aja
  • 带有 WSL2 的 VSCode - 由于 ping 无响应而延迟启动

    将 VSCode 与 WSL2 结合使用 直到上周一切都很好 从今天开始 我观察到启动 WSL 需要时间 以下是 VSCode 的日志 2021 02 22 06 00 31 458 Resolving wsl myubuntu2004 r
  • 为什么编译器保留一点堆栈空间而不是整个数组大小?

    下面的代码 int main int arr 120 return arr 0 编译成这样 sub rsp 360 mov eax DWORD PTR rsp 480 add rsp 360 ret 知道整数是 4 个字节 数组大小是 12
  • 在 .NET 中检测客户端断开连接的最佳实践?

    我正在用 C 开发一台服务器 它只能接受一个客户端 我需要知道该客户端何时断开连接才能接受另一个连接请求 我正在使用第一个 Socket 它连续监听连接请求Socket BeginAccept并接受或拒绝客户 当客户端被接受时 返回的新 S
  • Laravel Passport - 功能测试返回未经授权的 401

    我正在尝试测试我的登录端点 其中成功的响应将返回access token除其他事项外 我在用着RefreshDatabase 所以我更改了控制器上的登录方法来检索client secret via a DB称呼 我测试了一个dd 我可以确认
  • 从 C# 中以编程方式创建的 TextBox 中获取值

    我遇到了这个令人痒痒的问题 但我无法让代码工作 发布表单时如何从文本框中读取值 一些代码 protected override void CreateChildControls base CreateChildControls TextBo
  • $filter 嵌套级别与 $or、$gte、$lte 运算符

    我想过滤 MONGOdb 中的多重嵌套文档 示例 JSON id ObjectId 5b5c3afbcc43cb5ed64b7a04 id NumberLong 15015060 name 1801 Conf type NumberInt
  • 如何为 tiff 文件添加附加标签

    我正在尝试读取并保存带有一些附加标签的 tiff 文件 当我制作一个运行良好的新图像时 但是当我打开一个图像然后尝试写回一些元标记时 它不起作用 图像可以写入 但它将保留原始标签而不做任何更改 我附上了我的测试代码 非常感谢您的帮助 fro
  • SpringBoot应用程序中的@RabbitListener方法测试

    Code RabbitMQ 监听器 Component public class ServerThroughRabbitMQ implements ServerThroughAMQPBroker private static final A