2015-11-30 21 views
15

Codice:@RabbitListener test in SpringBoot app

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

} 

test di integrazione:

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

} 

Quando eseguo quel test separetly, tutto funziona bene, ma quando l'eseguo con altri test il ServerThroughRabbitMQ deriso non è in uso, in modo da alcuni cache molla a forza di usare vecchio ascoltatore coniglio.

ho cercato di debug e posso vedere, che corretto fagiolo viene autowired alla prova, ma per qualche motivo vecchio ascoltatore sta usando (fava vecchio instanceId = 1 nuovo bean deriso instanceId = 3) e il test non avendo (Non so come sia possibile, quindi se in caso di bean vecchio esistente presumo di ottenere un'eccezione autowire).

Ho cercato di usare @DirtiesContext BEFORE_CLASS, ma di fronte anoter problema (vedi here)

+0

avete la possibilità di condividere la parte del vostro problema di progetto tramite git (Sarebbe davvero utile controllare questo test con ulteriori esperimenti)? – Sergii

+0

Hai mai trovato una soluzione soddisfacente? – geld0r

risposta

2

RabbitMQ e Test di integrazione può essere difficile, in quanto Coniglio MQ mantiene una sorta di stato: - i messaggi provenienti da precedenti prove in code - gli ascoltatori da precedenti prove ancora in ascolto su code

ci sono diversi approcci:

  • Purge tutte le code prima di iniziare il test (che potrebbe essere wha t che intende per cleanTestQueues())
  • Elimina tutte le code (o utilizzare code temporanee) e ricreare prima di ogni prova
  • Utilizzando il Coniglio Admin API REST uccidendo ascoltatori o connessioni di test precedenti
  • eliminare il vhost e ricreare l'infrasture per ogni test (che è il modo più brutale)