|
28 | 28 | import static org.mockito.ArgumentMatchers.eq;
|
29 | 29 | import static org.mockito.BDDMockito.given;
|
30 | 30 | import static org.mockito.BDDMockito.willAnswer;
|
| 31 | +import static org.mockito.BDDMockito.willThrow; |
31 | 32 | import static org.mockito.Mockito.mock;
|
32 | 33 | import static org.mockito.Mockito.times;
|
33 | 34 | import static org.mockito.Mockito.verify;
|
|
42 | 43 | import org.junit.Test;
|
43 | 44 | import org.mockito.Mockito;
|
44 | 45 |
|
| 46 | +import org.springframework.amqp.core.MessageListener; |
45 | 47 | import org.springframework.amqp.rabbit.connection.ChannelProxy;
|
46 | 48 | import org.springframework.amqp.rabbit.connection.Connection;
|
47 | 49 | import org.springframework.amqp.rabbit.connection.ConnectionFactory;
|
@@ -265,6 +267,50 @@ public void testRemoveQueuesWhileNotConnected() throws Exception {
|
265 | 267 | container.stop();
|
266 | 268 | }
|
267 | 269 |
|
| 270 | + @Test |
| 271 | + public void testMonitorCancelsAfterBadAckEvenIfChannelReportsOpen() throws Exception { |
| 272 | + ConnectionFactory connectionFactory = mock(ConnectionFactory.class); |
| 273 | + Connection connection = mock(Connection.class); |
| 274 | + ChannelProxy channel = mock(ChannelProxy.class); |
| 275 | + Channel rabbitChannel = mock(Channel.class); |
| 276 | + given(channel.getTargetChannel()).willReturn(rabbitChannel); |
| 277 | + |
| 278 | + given(connectionFactory.createConnection()).willReturn(connection); |
| 279 | + given(connection.createChannel(anyBoolean())).willReturn(channel); |
| 280 | + given(channel.isOpen()).willReturn(true); |
| 281 | + given(channel.queueDeclarePassive(Mockito.anyString())) |
| 282 | + .willAnswer(invocation -> mock(AMQP.Queue.DeclareOk.class)); |
| 283 | + AtomicReference<Consumer> consumer = new AtomicReference<>(); |
| 284 | + final CountDownLatch latch1 = new CountDownLatch(1); |
| 285 | + final CountDownLatch latch2 = new CountDownLatch(1); |
| 286 | + willAnswer(inv -> { |
| 287 | + consumer.set(inv.getArgument(6)); |
| 288 | + latch1.countDown(); |
| 289 | + return "consumerTag"; |
| 290 | + }).given(channel).basicConsume(anyString(), anyBoolean(), anyString(), anyBoolean(), anyBoolean(), |
| 291 | + anyMap(), any(Consumer.class)); |
| 292 | + |
| 293 | + willThrow(new RuntimeException("bad ack")).given(channel).basicAck(1L, false); |
| 294 | + willAnswer(inv -> { |
| 295 | + consumer.get().handleCancelOk("consumerTag"); |
| 296 | + latch2.countDown(); |
| 297 | + return null; |
| 298 | + }).given(channel).basicCancel("consumerTag"); |
| 299 | + |
| 300 | + DirectMessageListenerContainer container = new DirectMessageListenerContainer(connectionFactory); |
| 301 | + container.setQueueNames("test"); |
| 302 | + container.setPrefetchCount(2); |
| 303 | + container.setMonitorInterval(100); |
| 304 | + container.setMessageListener(mock(MessageListener.class)); |
| 305 | + container.afterPropertiesSet(); |
| 306 | + container.start(); |
| 307 | + |
| 308 | + assertTrue(latch1.await(10, TimeUnit.SECONDS)); |
| 309 | + consumer.get().handleDelivery("consumerTag", envelope(1L), new BasicProperties(), new byte[1]); |
| 310 | + assertTrue(latch2.await(10, TimeUnit.SECONDS)); |
| 311 | + container.stop(); |
| 312 | + } |
| 313 | + |
268 | 314 | private Envelope envelope(long tag) {
|
269 | 315 | return new Envelope(tag, false, "", "");
|
270 | 316 | }
|
|
0 commit comments