Java @SpringBoot应用程序中的RabbitListener方法测试
代码: RabbitMQListener:Java @SpringBoot应用程序中的RabbitListener方法测试,java,spring,junit,spring-boot,rabbitmq,Java,Spring,Junit,Spring Boot,Rabbitmq,代码: RabbitMQListener: @Component public class ServerThroughRabbitMQ implements ServerThroughAMQPBroker { private static final AtomicLong ID_COUNTER=new AtomicLong(); private final long instanceId=ID_COUNTER.incrementAndGet(); @Autowired
@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@email.com";
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);
}
}
当我单独运行该测试时,一切正常,但当我与其他测试一起运行时,模拟服务器ThroughrabbitMQ没有被使用,因此一些spring缓存强制使用旧的rabbit侦听器
我试着调试它,我可以看到,正确的bean正在自动连接到测试,但由于某种原因,旧的侦听器正在使用(旧的bean字段instanceId=1新的模拟bean instanceId=3),并且测试失败(不确定这是怎么可能的,所以如果存在旧的bean,我假设会得到一个autowire异常)
我试图在_类之前使用@DirtiesContext,但面临另一个问题(请参见)RabbitMQ,集成测试可能很难,因为RabbitMQ保持某种状态: -来自队列中以前测试的消息 -以前测试中的侦听器仍在侦听队列 有几种方法:
- 在开始测试之前清除所有队列(这可能就是您所说的
)cleanTestQueues()
- 删除所有队列(或使用临时队列)并在每次测试之前重新创建它们
- 使用Rabbit Admin Rest API杀死以前测试的侦听器或连接
- 删除vhost并为每个测试重新创建基础设施(这是最残酷的方式)