|
1 | 1 | /*
|
2 |
| - * Copyright 2002-2021 the original author or authors. |
| 2 | + * Copyright 2002-2022 the original author or authors. |
3 | 3 | *
|
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License");
|
5 | 5 | * you may not use this file except in compliance with the License.
|
|
86 | 86 | import org.springframework.amqp.utils.test.TestUtils;
|
87 | 87 | import org.springframework.aop.support.AopUtils;
|
88 | 88 | import org.springframework.beans.DirectFieldAccessor;
|
| 89 | +import org.springframework.core.task.SimpleAsyncTaskExecutor; |
89 | 90 | import org.springframework.test.util.ReflectionTestUtils;
|
90 | 91 | import org.springframework.transaction.TransactionDefinition;
|
91 | 92 | import org.springframework.transaction.TransactionException;
|
|
106 | 107 | * @author Gary Russell
|
107 | 108 | * @author Artem Bilan
|
108 | 109 | * @author Mohammad Hewedy
|
| 110 | + * @author Yansong Ren |
109 | 111 | */
|
110 | 112 | public class SimpleMessageListenerContainerTests {
|
111 | 113 |
|
@@ -731,6 +733,30 @@ void filterMppNoDoubleAck() throws Exception {
|
731 | 733 | verifyNoMoreInteractions(listener);
|
732 | 734 | }
|
733 | 735 |
|
| 736 | + @Test |
| 737 | + void testWithConsumerStartWhenNotActive() { |
| 738 | + ConnectionFactory connectionFactory = mock(ConnectionFactory.class); |
| 739 | + Connection connection = mock(Connection.class); |
| 740 | + Channel channel = mock(Channel.class); |
| 741 | + given(connectionFactory.createConnection()).willReturn(connection); |
| 742 | + given(connection.createChannel(false)).willReturn(channel); |
| 743 | + |
| 744 | + SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory); |
| 745 | + // overwrite task execute. shutdown container before task execute. |
| 746 | + TestExecutor testExecutor = new TestExecutor(container); |
| 747 | + container.setTaskExecutor(testExecutor); |
| 748 | + container.start(); |
| 749 | + |
| 750 | + // then add queue for trigger container shutdown |
| 751 | + container.addQueueNames("bar"); |
| 752 | + |
| 753 | + // valid the 'start' countdown is 0. lastTask is AsyncMessageProcessingConsumer |
| 754 | + Runnable lastTask = testExecutor.getLastTask(); |
| 755 | + CountDownLatch start = TestUtils.getPropertyValue(lastTask, "start", CountDownLatch.class); |
| 756 | + |
| 757 | + assertThat(start.getCount()).isEqualTo(0L); |
| 758 | + } |
| 759 | + |
734 | 760 | private Answer<Object> messageToConsumer(final Channel mockChannel, final SimpleMessageListenerContainer container,
|
735 | 761 | final boolean cancel, final CountDownLatch latch) {
|
736 | 762 | return invocation -> {
|
@@ -784,4 +810,33 @@ protected void doRollback(DefaultTransactionStatus status) throws TransactionExc
|
784 | 810 |
|
785 | 811 | }
|
786 | 812 |
|
| 813 | + @SuppressWarnings("serial") |
| 814 | + private static final class TestExecutor extends SimpleAsyncTaskExecutor { |
| 815 | + |
| 816 | + private final SimpleMessageListenerContainer simpleMessageListenerContainer; |
| 817 | + |
| 818 | + private int shutdownCount = 0; |
| 819 | + |
| 820 | + private Runnable lastTask = null; |
| 821 | + |
| 822 | + private TestExecutor(SimpleMessageListenerContainer simpleMessageListenerContainer) { |
| 823 | + this.simpleMessageListenerContainer = simpleMessageListenerContainer; |
| 824 | + } |
| 825 | + |
| 826 | + public Runnable getLastTask() { |
| 827 | + return lastTask; |
| 828 | + } |
| 829 | + |
| 830 | + @Override |
| 831 | + public void execute(Runnable task) { |
| 832 | + // skip the first execution |
| 833 | + if (++shutdownCount > 1) { |
| 834 | + lastTask = task; |
| 835 | + // before execute, shutdown the container for test |
| 836 | + this.simpleMessageListenerContainer.shutdown(); |
| 837 | + } |
| 838 | + super.execute(task); |
| 839 | + } |
| 840 | + } |
| 841 | + |
787 | 842 | }
|
0 commit comments