|
22 | 22 | import static org.mockito.Matchers.any;
|
23 | 23 | import static org.mockito.Matchers.anyLong;
|
24 | 24 | import static org.mockito.Matchers.anyString;
|
| 25 | +import static org.mockito.Mockito.eq; |
25 | 26 | import static org.mockito.Mockito.inOrder;
|
26 | 27 | import static org.mockito.Mockito.mock;
|
27 | 28 | import static org.mockito.Mockito.spy;
|
@@ -308,6 +309,77 @@ public void onMessage(ConsumerRecord<Integer, String> data) {
|
308 | 309 | container.stop();
|
309 | 310 | }
|
310 | 311 |
|
| 312 | + @Test |
| 313 | + public void testRecordAckMockForeignThread() throws Exception { |
| 314 | + testRecordAckMockForeignThreadGuts(AckMode.MANUAL); |
| 315 | + } |
| 316 | + |
| 317 | + @Test |
| 318 | + public void testRecordAckMockForeignThreadImmediate() throws Exception { |
| 319 | + testRecordAckMockForeignThreadGuts(AckMode.MANUAL_IMMEDIATE); |
| 320 | + } |
| 321 | + |
| 322 | + @SuppressWarnings("unchecked") |
| 323 | + private void testRecordAckMockForeignThreadGuts(AckMode ackMode) throws Exception { |
| 324 | + ConsumerFactory<Integer, String> cf = mock(ConsumerFactory.class); |
| 325 | + Consumer<Integer, String> consumer = mock(Consumer.class); |
| 326 | + given(cf.createConsumer(anyString(), eq("clientId"))).willReturn(consumer); |
| 327 | + final Map<TopicPartition, List<ConsumerRecord<Integer, String>>> records = new HashMap<>(); |
| 328 | + records.put(new TopicPartition("foo", 0), Arrays.asList( |
| 329 | + new ConsumerRecord<>("foo", 0, 0L, 1, "foo"), |
| 330 | + new ConsumerRecord<>("foo", 0, 1L, 1, "bar"))); |
| 331 | + ConsumerRecords<Integer, String> consumerRecords = new ConsumerRecords<>(records); |
| 332 | + given(consumer.poll(anyLong())).willAnswer(i -> { |
| 333 | + Thread.sleep(50); |
| 334 | + return consumerRecords; |
| 335 | + }); |
| 336 | + TopicPartitionInitialOffset[] topicPartition = new TopicPartitionInitialOffset[] { |
| 337 | + new TopicPartitionInitialOffset("foo", 0) }; |
| 338 | + ContainerProperties containerProps = new ContainerProperties(topicPartition); |
| 339 | + containerProps.setAckMode(ackMode); |
| 340 | + final CountDownLatch latch = new CountDownLatch(2); |
| 341 | + final List<Acknowledgment> acks = new ArrayList<>(); |
| 342 | + final AtomicReference<Thread> consumerThread = new AtomicReference<>(); |
| 343 | + AcknowledgingMessageListener<Integer, String> messageListener = spy( |
| 344 | + new AcknowledgingMessageListener<Integer, String>() { |
| 345 | + |
| 346 | + @Override |
| 347 | + public void onMessage(ConsumerRecord<Integer, String> data, Acknowledgment acknowledgment) { |
| 348 | + acks.add(acknowledgment); |
| 349 | + consumerThread.set(Thread.currentThread()); |
| 350 | + latch.countDown(); |
| 351 | + if (latch.getCount() == 0) { |
| 352 | + records.clear(); |
| 353 | + } |
| 354 | + } |
| 355 | + |
| 356 | + }); |
| 357 | + |
| 358 | + final CountDownLatch commitLatch = new CountDownLatch(1); |
| 359 | + final AtomicReference<Thread> commitThread = new AtomicReference<>(); |
| 360 | + willAnswer(i -> { |
| 361 | + commitThread.set(Thread.currentThread()); |
| 362 | + commitLatch.countDown(); |
| 363 | + return null; |
| 364 | + } |
| 365 | + ).given(consumer).commitSync(any(Map.class)); |
| 366 | + |
| 367 | + containerProps.setMessageListener(messageListener); |
| 368 | + KafkaMessageListenerContainer<Integer, String> container = |
| 369 | + new KafkaMessageListenerContainer<>(cf, containerProps); |
| 370 | + container.setClientIdSuffix("clientId"); |
| 371 | + container.start(); |
| 372 | + assertThat(latch.await(10, TimeUnit.SECONDS)).isTrue(); |
| 373 | + acks.get(1).acknowledge(); |
| 374 | + assertThat(commitLatch.await(10, TimeUnit.SECONDS)).isTrue(); |
| 375 | + InOrder inOrder = inOrder(messageListener, consumer); |
| 376 | + inOrder.verify(consumer).poll(1000); |
| 377 | + inOrder.verify(messageListener, times(2)).onMessage(any(ConsumerRecord.class), any(Acknowledgment.class)); |
| 378 | + inOrder.verify(consumer).commitSync(any(Map.class)); |
| 379 | + container.stop(); |
| 380 | + assertThat(commitThread.get()).isSameAs(consumerThread.get()); |
| 381 | + } |
| 382 | + |
311 | 383 | @SuppressWarnings("unchecked")
|
312 | 384 | @Test
|
313 | 385 | public void testBrokerDownEvent() throws Exception {
|
|
0 commit comments