Тесты MockBean и несколько потребителей \ Контексты приложений с помощью Spring AMQP - PullRequest
0 голосов
/ 22 сентября 2018

В настоящее время у меня возникла проблема с тестированием потребителей 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. Как я должен правильно проводить тестирование бобов с потребителями весной?
  2. Похоже, что Spring создает новый ApplicationContext для каждого класса тестирования, о чем свидетельствует увеличение числа потребителей при последующих запусках теста.Похоже, что @MockBean влияет на ключ кэша ApplicationContext (см .: Пересмешивание и отслеживание компонентов в Spring Boot ) и, вероятно, объясняет, почему существует несколько контекстов приложения.Но как мне запретить потребителям в других устаревших контекстах приложения потреблять мои тестовые сообщения?

Я решил эту проблему здесь: RabbitMQ MockBean BugJar

1 Ответ

0 голосов
/ 22 сентября 2018

Добавьте @DirtiesContext к каждому тестовому классу, чтобы закрыть кешированный контекст.

...