1
1
/*
2
- * Copyright 2002-2014 the original author or authors.
2
+ * Copyright 2002-2016 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.
16
16
17
17
package org .springframework .jms .listener ;
18
18
19
+ import java .util .concurrent .CountDownLatch ;
20
+ import java .util .concurrent .TimeUnit ;
19
21
import javax .jms .Connection ;
20
22
import javax .jms .ConnectionFactory ;
21
23
import javax .jms .Destination ;
32
34
import static org .mockito .BDDMockito .*;
33
35
34
36
/**
35
- *
36
37
* @author Stephane Nicoll
37
38
*/
38
39
public class DefaultMessageListenerContainerTests {
39
40
40
41
@ Test
41
42
public void applyBackOff () {
42
- BackOff mock = mock (BackOff .class );
43
+ BackOff backOff = mock (BackOff .class );
43
44
BackOffExecution execution = mock (BackOffExecution .class );
44
45
given (execution .nextBackOff ()).willReturn (BackOffExecution .STOP );
45
- given (mock .start ()).willReturn (execution );
46
+ given (backOff .start ()).willReturn (execution );
46
47
47
- DefaultMessageListenerContainer container = createContainer (mock , createFailingContainerFactory ());
48
+ DefaultMessageListenerContainer container = createContainer (createFailingContainerFactory ());
49
+ container .setBackOff (backOff );
48
50
container .start ();
49
51
assertEquals (true , container .isRunning ());
50
52
51
53
container .refreshConnectionUntilSuccessful ();
52
54
53
55
assertEquals (false , container .isRunning ());
54
- verify (mock ).start ();
56
+ verify (backOff ).start ();
55
57
verify (execution ).nextBackOff ();
56
58
}
57
59
58
60
@ Test
59
61
public void applyBackOffRetry () {
60
- BackOff mock = mock (BackOff .class );
62
+ BackOff backOff = mock (BackOff .class );
61
63
BackOffExecution execution = mock (BackOffExecution .class );
62
64
given (execution .nextBackOff ()).willReturn (50L , BackOffExecution .STOP );
63
- given (mock .start ()).willReturn (execution );
65
+ given (backOff .start ()).willReturn (execution );
64
66
65
- DefaultMessageListenerContainer container = createContainer (mock , createFailingContainerFactory ());
67
+ DefaultMessageListenerContainer container = createContainer (createFailingContainerFactory ());
68
+ container .setBackOff (backOff );
66
69
container .start ();
67
70
container .refreshConnectionUntilSuccessful ();
68
71
69
72
assertEquals (false , container .isRunning ());
70
- verify (mock ).start ();
73
+ verify (backOff ).start ();
71
74
verify (execution , times (2 )).nextBackOff ();
72
75
}
73
76
74
77
@ Test
75
78
public void recoverResetBackOff () {
76
- BackOff mock = mock (BackOff .class );
79
+ BackOff backOff = mock (BackOff .class );
77
80
BackOffExecution execution = mock (BackOffExecution .class );
78
81
given (execution .nextBackOff ()).willReturn (50L , 50L , 50L ); // 3 attempts max
79
- given (mock .start ()).willReturn (execution );
82
+ given (backOff .start ()).willReturn (execution );
80
83
81
- DefaultMessageListenerContainer container = createContainer (mock , createRecoverableContainerFactory (1 ));
84
+ DefaultMessageListenerContainer container = createContainer (createRecoverableContainerFactory (1 ));
85
+ container .setBackOff (backOff );
82
86
container .start ();
83
87
container .refreshConnectionUntilSuccessful ();
84
88
85
89
assertEquals (true , container .isRunning ());
86
- verify (mock ).start ();
90
+ verify (backOff ).start ();
87
91
verify (execution , times (1 )).nextBackOff (); // only on attempt as the second one lead to a recovery
88
92
}
89
93
90
- private DefaultMessageListenerContainer createContainer (BackOff backOff , ConnectionFactory connectionFactory ) {
94
+ @ Test
95
+ public void runnableIsInvokedEvenIfContainerIsNotRunning () throws InterruptedException {
96
+ DefaultMessageListenerContainer container = createRunningContainer ();
97
+ container .stop ();
98
+
99
+ // container is stopped but should nevertheless invoke the runnable argument
100
+ TestRunnable runnable2 = new TestRunnable ();
101
+ container .stop (runnable2 );
102
+ runnable2 .waitForCompletion ();
103
+ }
91
104
92
- Destination destination = new Destination () {};
93
105
106
+ private DefaultMessageListenerContainer createRunningContainer () {
107
+ DefaultMessageListenerContainer container = createContainer (createSuccessfulConnectionFactory ());
108
+ container .afterPropertiesSet ();
109
+ container .start ();
110
+ return container ;
111
+ }
112
+
113
+ private DefaultMessageListenerContainer createContainer (ConnectionFactory connectionFactory ) {
114
+ Destination destination = new Destination () {};
94
115
95
116
DefaultMessageListenerContainer container = new DefaultMessageListenerContainer ();
96
117
container .setConnectionFactory (connectionFactory );
97
118
container .setCacheLevel (DefaultMessageListenerContainer .CACHE_NONE );
98
119
container .setDestination (destination );
99
- container .setBackOff (backOff );
100
120
return container ;
101
-
102
121
}
103
122
104
123
private ConnectionFactory createFailingContainerFactory () {
@@ -112,8 +131,8 @@ public Object answer(InvocationOnMock invocation) throws Throwable {
112
131
});
113
132
return connectionFactory ;
114
133
}
115
- catch (JMSException e ) {
116
- throw new IllegalStateException (); // never happen
134
+ catch (JMSException ex ) {
135
+ throw new IllegalStateException (ex ); // never happen
117
136
}
118
137
}
119
138
@@ -122,7 +141,6 @@ private ConnectionFactory createRecoverableContainerFactory(final int failingAtt
122
141
ConnectionFactory connectionFactory = mock (ConnectionFactory .class );
123
142
given (connectionFactory .createConnection ()).will (new Answer <Object >() {
124
143
int currentAttempts = 0 ;
125
-
126
144
@ Override
127
145
public Object answer (InvocationOnMock invocation ) throws Throwable {
128
146
currentAttempts ++;
@@ -136,8 +154,35 @@ public Object answer(InvocationOnMock invocation) throws Throwable {
136
154
});
137
155
return connectionFactory ;
138
156
}
139
- catch (JMSException e ) {
140
- throw new IllegalStateException (); // never happen
157
+ catch (JMSException ex ) {
158
+ throw new IllegalStateException (ex ); // never happen
159
+ }
160
+ }
161
+
162
+ private ConnectionFactory createSuccessfulConnectionFactory () {
163
+ try {
164
+ ConnectionFactory connectionFactory = mock (ConnectionFactory .class );
165
+ given (connectionFactory .createConnection ()).willReturn (mock (Connection .class ));
166
+ return connectionFactory ;
167
+ }
168
+ catch (JMSException ex ) {
169
+ throw new IllegalStateException (ex ); // never happen
170
+ }
171
+ }
172
+
173
+
174
+ private static class TestRunnable implements Runnable {
175
+
176
+ private final CountDownLatch countDownLatch = new CountDownLatch (1 );
177
+
178
+ @ Override
179
+ public void run () {
180
+ this .countDownLatch .countDown ();
181
+ }
182
+
183
+ public void waitForCompletion () throws InterruptedException {
184
+ this .countDownLatch .await (2 , TimeUnit .SECONDS );
185
+ assertEquals ("callback was not invoked" , 0 , this .countDownLatch .getCount ());
141
186
}
142
187
}
143
188
0 commit comments