Skip to content

Commit d73f4ff

Browse files
garyrussellartembilan
authored andcommittedDec 20, 2017
AMQP-791: Support JUnit5
JIRA: https://jira.spring.io/browse/AMQP-791 - refactor `BrokerRunning` JUnit4 `@Rule` so it can be invoked from an `ExecutionCondition`. - Add `@RabbitAvailable` annotation with queue list and auto-delete queues at the end of the class; purge them between tests. * Implement `ParameterResolver` to access the rule's connection factory. * Support CTOR Injection and `BrokerRunning` Injection - user might want to invoke methods such as `deleteQueues()`. * Patches omitted from previous commit * WIP - Spring * Polishing - PR Comments * Convert `RabbitTemplateMPPIntegrationTests` - JUnit5 * Remove bogus test * Docs + `@LongRunning` * Polishing - PR Comments
1 parent 48412b9 commit d73f4ff

File tree

15 files changed

+840
-184
lines changed

15 files changed

+840
-184
lines changed
 

‎build.gradle

+23-4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ buildscript {
88
classpath 'me.champeau.gradle:gradle-javadoc-hotfix-plugin:0.1'
99
classpath 'io.spring.gradle:dependency-management-plugin:1.0.2.RELEASE'
1010
classpath 'io.spring.gradle:spring-io-plugin:0.0.8.RELEASE'
11+
classpath 'org.junit.platform:junit-platform-gradle-plugin:1.0.2'
1112
}
1213
}
1314

@@ -87,7 +88,10 @@ subprojects { subproject ->
8788
ext {
8889
hamcrestVersion = '1.3'
8990
jackson2Version = '2.9.1'
90-
junitVersion = '4.12'
91+
junit4Version = '4.12'
92+
junitJupiterVersion = '5.0.2'
93+
junitPlatformVersion = '1.0.2'
94+
junitVintageVersion = '4.12.2'
9195
log4jVersion = '2.8.2'
9296
logbackVersion = '1.2.3'
9397
mockitoVersion = '2.11.0'
@@ -112,7 +116,7 @@ subprojects { subproject ->
112116

113117
// dependencies that are common across all java projects
114118
dependencies {
115-
testCompile ("junit:junit:$junitVersion") {
119+
testCompile ("junit:junit:$junit4Version") {
116120
exclude group: 'org.hamcrest', module: 'hamcrest-core'
117121
}
118122
testCompile "org.apache.logging.log4j:log4j-core:$log4jVersion"
@@ -123,6 +127,18 @@ subprojects { subproject ->
123127
testCompile "org.springframework:spring-test:$springVersion"
124128
testCompile "org.slf4j:slf4j-log4j12:$slf4jVersion" // amqp-client now uses SLF4J
125129
testRuntime "org.apache.logging.log4j:log4j-jcl:$log4jVersion"
130+
131+
testCompile "org.junit.jupiter:junit-jupiter-api:${junitJupiterVersion}"
132+
testRuntime "org.junit.jupiter:junit-jupiter-engine:${junitJupiterVersion}"
133+
testRuntime "org.junit.platform:junit-platform-commons:${junitPlatformVersion}"
134+
testRuntime "org.junit.platform:junit-platform-launcher:${junitPlatformVersion}"
135+
136+
// To support JUnit 4 tests
137+
testRuntime "org.junit.vintage:junit-vintage-engine:${junitVintageVersion}"
138+
139+
// To avoid compiler warnings about @API annotations in JUnit code
140+
testCompileOnly 'org.apiguardian:apiguardian-api:1.0.0'
141+
126142
}
127143

128144
// enable all compiler warnings; individual projects may customize further
@@ -265,12 +281,15 @@ project('spring-rabbit-junit') {
265281
dependencies { // no spring-amqp dependencies allowed
266282

267283
compile "org.springframework:spring-core:$springVersion"
268-
compile "junit:junit:$junitVersion"
284+
compile "junit:junit:$junit4Version"
269285
compile "com.rabbitmq:amqp-client:$rabbitmqVersion"
270286
compile ("com.rabbitmq:http-client:$rabbitmqHttpClientVersion") {
271287
exclude group: 'org.springframework', module: 'spring-web'
272288
}
273289
compile "org.springframework:spring-web:$springVersion"
290+
compile "org.junit.jupiter:junit-jupiter-api:${junitJupiterVersion}"
291+
compile "org.junit.platform:junit-platform-commons:${junitPlatformVersion}"
292+
compileOnly 'org.apiguardian:apiguardian-api:1.0.0'
274293

275294
}
276295

@@ -282,7 +301,7 @@ project('spring-rabbit-test') {
282301
dependencies {
283302

284303
compile project(":spring-rabbit")
285-
compile ("junit:junit:$junitVersion") {
304+
compile ("junit:junit:$junit4Version") {
286305
exclude group: 'org.hamcrest', module: 'hamcrest-core'
287306
}
288307
compile "org.hamcrest:hamcrest-all:$hamcrestVersion"

‎spring-rabbit-junit/src/main/java/org/springframework/amqp/rabbit/junit/BrokerRunning.java

+60-36
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import static org.junit.Assert.fail;
2020

2121
import java.io.IOException;
22+
import java.net.MalformedURLException;
23+
import java.net.URISyntaxException;
2224
import java.nio.ByteBuffer;
2325
import java.util.ArrayList;
2426
import java.util.Arrays;
@@ -367,38 +369,8 @@ public Statement apply(Statement base, Description description) {
367369
Channel channel = null;
368370

369371
try {
370-
connection = connectionFactory.newConnection();
371-
connection.setId(generateId());
372-
channel = connection.createChannel();
373-
374-
for (String queueName : this.queues) {
375-
376-
if (this.purge) {
377-
logger.debug("Deleting queue: " + queueName);
378-
// Delete completely - gets rid of consumers and bindings as well
379-
channel.queueDelete(queueName);
380-
}
381-
382-
if (isDefaultQueue(queueName)) {
383-
// Just for test probe.
384-
channel.queueDelete(queueName);
385-
}
386-
else {
387-
channel.queueDeclare(queueName, true, false, false, null);
388-
}
389-
}
390-
brokerOffline.put(this.port, false);
391-
if (!this.assumeOnline) {
392-
Assume.assumeTrue(brokerOffline.get(this.port));
393-
}
394-
395-
if (this.management) {
396-
Client client = new Client(getAdminUri(), this.adminUser, this.adminPassword);
397-
if (!client.alivenessTest("/")) {
398-
throw new RuntimeException("Aliveness test failed for localhost:15672 guest/quest; "
399-
+ "management not available");
400-
}
401-
}
372+
connection = getConnection(connectionFactory);
373+
channel = createQueues(connection);
402374
}
403375
catch (Exception e) {
404376
logger.warn("Not executing tests because basic connectivity test failed: " + e.getMessage());
@@ -419,7 +391,59 @@ public Statement apply(Statement base, Description description) {
419391
return super.apply(base, description);
420392
}
421393

422-
private boolean fatal() {
394+
public void isUp() throws Exception {
395+
Connection connection = getConnectionFactory().newConnection();
396+
Channel channel = null;
397+
try {
398+
channel = createQueues(connection);
399+
}
400+
finally {
401+
closeResources(connection, channel);
402+
}
403+
}
404+
405+
private Connection getConnection(ConnectionFactory connectionFactory) throws IOException, TimeoutException {
406+
Connection connection = connectionFactory.newConnection();
407+
connection.setId(generateId());
408+
return connection;
409+
}
410+
411+
private Channel createQueues(Connection connection) throws IOException, MalformedURLException, URISyntaxException {
412+
Channel channel;
413+
channel = connection.createChannel();
414+
415+
for (String queueName : this.queues) {
416+
417+
if (this.purge) {
418+
logger.debug("Deleting queue: " + queueName);
419+
// Delete completely - gets rid of consumers and bindings as well
420+
channel.queueDelete(queueName);
421+
}
422+
423+
if (isDefaultQueue(queueName)) {
424+
// Just for test probe.
425+
channel.queueDelete(queueName);
426+
}
427+
else {
428+
channel.queueDeclare(queueName, true, false, false, null);
429+
}
430+
}
431+
brokerOffline.put(this.port, false);
432+
if (!this.assumeOnline) {
433+
Assume.assumeTrue(brokerOffline.get(this.port));
434+
}
435+
436+
if (this.management) {
437+
Client client = new Client(getAdminUri(), this.adminUser, this.adminPassword);
438+
if (!client.alivenessTest("/")) {
439+
throw new RuntimeException("Aliveness test failed for localhost:15672 guest/quest; "
440+
+ "management not available");
441+
}
442+
}
443+
return channel;
444+
}
445+
446+
public static boolean fatal() {
423447
String serversRequired = System.getenv(BROKER_REQUIRED);
424448
if (Boolean.parseBoolean(serversRequired)) {
425449
logger.error("RABBITMQ IS REQUIRED BUT NOT AVAILABLE");
@@ -465,7 +489,7 @@ public void removeTestQueues(String... additionalQueues) {
465489
Channel channel = null;
466490

467491
try {
468-
connection = connectionFactory.newConnection();
492+
connection = getConnection(connectionFactory);
469493
connection.setId(generateId() + ".queueDelete");
470494
channel = connection.createChannel();
471495

@@ -491,7 +515,7 @@ public void deleteQueues(String... queues) {
491515
Channel channel = null;
492516

493517
try {
494-
connection = connectionFactory.newConnection();
518+
connection = getConnection(connectionFactory);
495519
connection.setId(generateId() + ".queueDelete");
496520
channel = connection.createChannel();
497521

@@ -517,7 +541,7 @@ public void deleteExchanges(String... exchanges) {
517541
Channel channel = null;
518542

519543
try {
520-
connection = connectionFactory.newConnection();
544+
connection = getConnection(connectionFactory);
521545
connection.setId(generateId() + ".exchangeDelete");
522546
channel = connection.createChannel();
523547

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright 2017 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.amqp.rabbit.junit;
18+
19+
import java.lang.annotation.Documented;
20+
import java.lang.annotation.ElementType;
21+
import java.lang.annotation.Retention;
22+
import java.lang.annotation.RetentionPolicy;
23+
import java.lang.annotation.Target;
24+
25+
import org.junit.jupiter.api.extension.ExtendWith;
26+
27+
/**
28+
* Test classes annotated with this will not run if an environment variable or system
29+
* property (default {@code RUN_LONG_INTEGRATION_TESTS}) is not present or does not have
30+
* the value that {@link Boolean#parseBoolean(String)} evaluates to {@code true}.
31+
*
32+
* @author Gary Russell
33+
* @since 2.0.2
34+
*
35+
*/
36+
@ExtendWith(LongRunningIntegrationTestCondition.class)
37+
@Target({ ElementType.TYPE })
38+
@Retention(RetentionPolicy.RUNTIME)
39+
@Documented
40+
public @interface LongRunning {
41+
42+
/**
43+
* The name of the variable/property used to determine whether long runnning tests
44+
* should run.
45+
* @return the name of the variable/property.
46+
*/
47+
String value() default LongRunningIntegrationTest.RUN_LONG_INTEGRATION_TESTS;
48+
49+
}

‎spring-rabbit-junit/src/main/java/org/springframework/amqp/rabbit/junit/LongRunningIntegrationTest.java

+20-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2013-2016 the original author or authors.
2+
* Copyright 2013-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -36,12 +36,21 @@ public class LongRunningIntegrationTest extends TestWatcher {
3636

3737
private final static Log logger = LogFactory.getLog(LongRunningIntegrationTest.class);
3838

39-
private static final String RUN_LONG_PROP = "RUN_LONG_INTEGRATION_TESTS";
39+
public static final String RUN_LONG_INTEGRATION_TESTS = "RUN_LONG_INTEGRATION_TESTS";
4040

4141
private boolean shouldRun = false;
4242

4343
public LongRunningIntegrationTest() {
44-
for (String value: new String[] { System.getenv(RUN_LONG_PROP), System.getProperty(RUN_LONG_PROP) }) {
44+
this(RUN_LONG_INTEGRATION_TESTS);
45+
}
46+
47+
/**
48+
* Check using a custom variable/property name.
49+
* @param property the variable/property name.
50+
* @since 2.0.2
51+
*/
52+
public LongRunningIntegrationTest(String property) {
53+
for (String value: new String[] { System.getenv(property), System.getProperty(property) }) {
4554
if (Boolean.parseBoolean(value)) {
4655
this.shouldRun = true;
4756
break;
@@ -58,4 +67,12 @@ public Statement apply(Statement base, Description description) {
5867
return super.apply(base, description);
5968
}
6069

70+
/**
71+
* Return true if the test should run.
72+
* @return true to run.
73+
*/
74+
public boolean isShouldRun() {
75+
return this.shouldRun;
76+
}
77+
6178
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright 2017 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.amqp.rabbit.junit;
18+
19+
import java.lang.reflect.AnnotatedElement;
20+
import java.util.Optional;
21+
22+
import org.junit.jupiter.api.extension.ConditionEvaluationResult;
23+
import org.junit.jupiter.api.extension.ExecutionCondition;
24+
import org.junit.jupiter.api.extension.ExtensionContext;
25+
import org.junit.platform.commons.util.AnnotationUtils;
26+
27+
import org.springframework.util.StringUtils;
28+
29+
/**
30+
* {@link ExecutionCondition} to skip long running tests unless an environment
31+
* variable or property is set.
32+
*
33+
* @author Gary Russell
34+
* @since 2.0.2
35+
* @see LongRunning
36+
*/
37+
public class LongRunningIntegrationTestCondition implements ExecutionCondition {
38+
39+
private static final ConditionEvaluationResult ENABLED = ConditionEvaluationResult.enabled(
40+
"@LongRunning is not present");
41+
42+
@Override
43+
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
44+
Optional<AnnotatedElement> element = context.getElement();
45+
Optional<LongRunning> longRunning = AnnotationUtils.findAnnotation(element, LongRunning.class);
46+
if (longRunning.isPresent()) {
47+
String property = longRunning.get().value();
48+
if (!StringUtils.hasText(property)) {
49+
property = LongRunningIntegrationTest.RUN_LONG_INTEGRATION_TESTS;
50+
}
51+
LongRunningIntegrationTest lrit = new LongRunningIntegrationTest(property);
52+
return lrit.isShouldRun() ? ConditionEvaluationResult.enabled("Long running tests must run")
53+
: ConditionEvaluationResult.disabled("Long running tests are skipped");
54+
}
55+
return ENABLED;
56+
}
57+
58+
}

0 commit comments

Comments
 (0)
Please sign in to comment.