使用Spring AMQP的MockBean测试和多个使用者\应用上下文

时间:2018-09-21 22:10:25

标签: spring-boot rabbitmq mockito spring-amqp

我目前在用模拟测试RabbitMQ消费者时遇到问题。问题似乎是,一个测试类与应用程序上下文一起运行,并且没有任何模拟,这与预期的一样。下一个要运行的测试类将设置一些它希望使用者使用的模拟,但是,当测试运行并发送消息时,非模拟的使用者会从为第一个测试类创建的应用程序上下文中获取消息。结果我的第二项测试失败了。

这是第一个测试:

@SpringBootTest
public class DemoApplicationTests extends AbstractTestNGSpringContextTests {

    @Autowired
    private RabbitAdmin rabbitAdmin;

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Test(priority = 1)
    public void contextLoads() {
        logger.info("=============== CONSUMERS: " + rabbitAdmin.getQueueProperties(USER_MESSAGING_QUEUE).get(RabbitAdmin.QUEUE_CONSUMER_COUNT));
    }
}

第二项测试:

@SpringBootTest
public class UserServiceTests extends AbstractTestNGSpringContextTests {

    @Autowired
    private UserService userService;

    @Autowired
    private UserMessageConsumer userMessageConsumer;

    @MockBean
    @Autowired
    private ThirdPartyUserDataClient thirdPartyUserDataClient;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private RabbitAdmin rabbitAdmin;

    @Test(priority = 2)
    public void createUpdateUserTest() {

        logger.info("=============== CONSUMERS: " + rabbitAdmin.getQueueProperties(USER_MESSAGING_QUEUE).get(RabbitAdmin.QUEUE_CONSUMER_COUNT));

        String additionalData = org.apache.commons.lang3.RandomStringUtils.random(5);
        Mockito.when(thirdPartyUserDataClient.getAdditionalUserData(ArgumentMatchers.anyLong())).thenReturn(additionalData);

        User user = new User();
        user.setName("Test User");
        user.setState(UserState.PENDING);

        user = userService.createUser(user);

        Assert.assertNotNull(user.getId());

        User finalUser = user;
        Awaitility.await().until(() -> {
            User user2 = userService.getUserById(finalUser.getId());
            return finalUser != null && additionalData.equals(user2.getAdditionalData());
        });

        user.setState(UserState.CREATED);
        user = userService.updateUser(user);

        Assert.assertEquals(UserState.CREATED, user.getState());

    }

}

消费者:

@Component
public class UserMessageConsumer {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    public static final String FAILED_TO_GET_ADDITIONAL_DATA = "FAILED_TO_GET_ADDITIONAL_DATA";

    @Autowired
    private UserService userService;

    @Autowired
    private ThirdPartyUserDataClient thirdPartyUserDataClient;

    public void handleUserCreatedMessage(UserCreatedMessage userCreatedMessage) {

        Long userId = userCreatedMessage.getUserId();
        User user = userService.getUserById(userId);

        if (user != null) {
            String additionalData;

            try {
                additionalData = thirdPartyUserDataClient.getAdditionalUserData(userId);
                logger.info("Successfully retrieved additional data [{}] for user [{}].", additionalData, userId);
            } catch (HttpClientErrorException ex) {
                additionalData = FAILED_TO_GET_ADDITIONAL_DATA;
                logger.warn("Failed to retrieve additional data for user [{}].", userId, ex);
            }

            user.setAdditionalData(additionalData);
            userService.updateUser(user);
        }

    }

}

这带来了两个相关的问题:

  1. 我应该如何正确地与消费者进行模拟bean测试 弹簧?
  2. 看起来Spring正在提出一个新的 每个测试类的ApplicationContext,由在后续测试运行中增加的使用者计数指示。它出现 @MockBean影响ApplicationContext的缓存键(请参阅: Mocking and Spying Beans in Spring Boot),并可能解释了为什么存在多个应用程序上下文。 但是如何在其他过时的应用程序上下文中阻止使用者 消耗我的测试消息吗?

我已经在这里打了这个问题:RabbitMQ MockBean BugJar

1 个答案:

答案 0 :(得分:1)

向每个测试类添加p_persist_reg_CRC_calc: process (Clk_50Mhz) begin if falling_edge(Clk_50Mhz) then if crc_rx_init <= '1' then flash_crc_calc <= (others =>'0'); else flash_crc_calc <= (others =>'1'); end if; end if; end process p_persist_reg_CRC_calc; 以关闭缓存的上下文。