2015-11-30 18 views
15

Kod:@RabbitListener w SpringBoot aplikacji

RabbitMQListener:

@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) { 
     ..... 
    } 

ServerConfig:

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

    } 

TestConfig:

@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,...); 
    } 

} 

badania integracji:

@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]"; 
    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); 
    } 

} 

Kiedy uruchomić ten test separetly, wszystko działa poprawnie, ale kiedy go uruchomić z innych testach szydzili ServerThroughRabbitMQ nie jest używany, więc niektóre buforuje wiosenne zmusić używać starego królika słuchacza.

Próbowałem go debugować i widzę, że poprawny komponent bean jest autowyredowany do testu, ale z jakiegoś powodu stary odbiornik używa (stare pole bean instanceId = 1 nowy szykowany instanceId = 3) i test nie działa (Nie wiem, jak to jest możliwe, więc jeśli w przypadku istniejącego starego komponentu, zakładam, że otrzymam wyjątek autowire).

Próbowałem użyć @DirtiesContext BEFORE_CLASS, ale w obliczu anoter problem (patrz here)

+0

czy masz okazję podzielić się swoją częścią problemu z projektem za pomocą git (byłoby naprawdę przydatne, aby sprawdzić te testy z dodatkowymi eksperymentami)? – Sergii

+0

Czy kiedykolwiek znalazłeś satysfakcjonujące rozwiązanie? – geld0r

Odpowiedz

2

RabbitMQ i testowanie Integracja może być trudne, ponieważ Królik MQ utrzymuje jakąś Stan: - wiadomości z poprzednich testów w kolejkach - słuchacze z poprzednich testów nadal słuchać na kolejkach

Istnieją różne podejścia:

  • Purge wszystkie kolejki przed rozpoczęciem testu (które mogą być wha t masz na myśli przez cleanTestQueues())
  • Usuń wszystkie kolejki (lub użyć kolejki tymczasowe) i odtworzyć je przed każdym badaniem
  • Korzystanie królika Admin API REST zabijania słuchaczy lub połączenia z poprzednich testów
  • usunąć ten vhosta i odtworzenie infrasture dla każdego testu (który jest najbardziej brutalny)