mirror of
https://github.com/apache/activemq-artemis.git
synced 2025-03-08 18:29:20 +00:00
ARTEMIS-737 Improving Tests by checking thread leaks and Waiting condition, also adding docs
This commit is contained in:
parent
32b7c039d8
commit
03b3b9fa80
@ -31,7 +31,7 @@ import org.apache.activemq.artemis.api.core.client.ServerLocator;
|
||||
* <pre><code>
|
||||
* public class SimpleTest {
|
||||
* {@code @Rule}
|
||||
* public ActiveMQConsumerResource producer = new ActiveMQProducerResource( "vm://0", "test.queue" );
|
||||
* public ActiveMQConsumerResource client = new ActiveMQProducerResource( "vm://0", "test.queue" );
|
||||
*
|
||||
* {@code @Test}
|
||||
* public void testSomething() throws Exception {
|
||||
|
@ -0,0 +1,223 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.activemq.artemis.junit;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
|
||||
import org.apache.activemq.artemis.core.remoting.impl.invm.InVMConnector;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.junit.Assert;
|
||||
import org.junit.rules.ExternalResource;
|
||||
|
||||
/**
|
||||
* Messaging tests are usually Thread intensive and a thread leak or a server leakage may affect future tests.
|
||||
* This Rule will prevent Threads leaking from one test into another by checking left over threads.
|
||||
* This will also clear Client Thread Pools from ActiveMQClient.
|
||||
*/
|
||||
public class ThreadLeakCheckRule extends ExternalResource {
|
||||
private static Logger log = Logger.getLogger(ThreadLeakCheckRule.class);
|
||||
|
||||
private static Set<String> knownThreads = new HashSet<>();
|
||||
|
||||
boolean enabled = true;
|
||||
|
||||
private Map<Thread, StackTraceElement[]> previousThreads;
|
||||
|
||||
public void disable() {
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override to set up your specific external resource.
|
||||
*
|
||||
* @throws if setup fails (which will disable {@code after}
|
||||
*/
|
||||
@Override
|
||||
protected void before() throws Throwable {
|
||||
// do nothing
|
||||
|
||||
previousThreads = Thread.getAllStackTraces();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Override to tear down your specific external resource.
|
||||
*/
|
||||
@Override
|
||||
protected void after() {
|
||||
ActiveMQClient.clearThreadPools();
|
||||
InVMConnector.resetThreadPool();
|
||||
|
||||
try {
|
||||
if (enabled) {
|
||||
boolean failed = true;
|
||||
|
||||
boolean failedOnce = false;
|
||||
|
||||
long timeout = System.currentTimeMillis() + 60000;
|
||||
while (failed && timeout > System.currentTimeMillis()) {
|
||||
failed = checkThread();
|
||||
|
||||
if (failed) {
|
||||
failedOnce = true;
|
||||
forceGC();
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
}
|
||||
catch (Throwable e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
Assert.fail("Thread leaked");
|
||||
}
|
||||
else if (failedOnce) {
|
||||
System.out.println("******************** Threads cleared after retries ********************");
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
enabled = true;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
// clearing just to help GC
|
||||
previousThreads = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static int failedGCCalls = 0;
|
||||
|
||||
public static void forceGC() {
|
||||
|
||||
if (failedGCCalls >= 10) {
|
||||
log.info("ignoring forceGC call since it seems System.gc is not working anyways");
|
||||
return;
|
||||
}
|
||||
log.info("#test forceGC");
|
||||
CountDownLatch finalized = new CountDownLatch(1);
|
||||
WeakReference<DumbReference> dumbReference = new WeakReference<>(new DumbReference(finalized));
|
||||
|
||||
long timeout = System.currentTimeMillis() + 1000;
|
||||
|
||||
// A loop that will wait GC, using the minimal time as possible
|
||||
while (!(dumbReference.get() == null && finalized.getCount() == 0) && System.currentTimeMillis() < timeout) {
|
||||
System.gc();
|
||||
System.runFinalization();
|
||||
try {
|
||||
finalized.await(100, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
|
||||
if (dumbReference.get() != null) {
|
||||
failedGCCalls++;
|
||||
log.info("It seems that GC is disabled at your VM");
|
||||
}
|
||||
else {
|
||||
// a success would reset the count
|
||||
failedGCCalls = 0;
|
||||
}
|
||||
log.info("#test forceGC Done ");
|
||||
}
|
||||
public static void removeKownThread(String name) {
|
||||
knownThreads.remove(name);
|
||||
}
|
||||
|
||||
public static void addKownThread(String name) {
|
||||
knownThreads.add(name);
|
||||
}
|
||||
|
||||
private boolean checkThread() {
|
||||
boolean failedThread = false;
|
||||
|
||||
Map<Thread, StackTraceElement[]> postThreads = Thread.getAllStackTraces();
|
||||
|
||||
if (postThreads != null && previousThreads != null && postThreads.size() > previousThreads.size()) {
|
||||
|
||||
|
||||
for (Thread aliveThread : postThreads.keySet()) {
|
||||
if (aliveThread.isAlive() && !isExpectedThread(aliveThread) && !previousThreads.containsKey(aliveThread)) {
|
||||
if (!failedThread) {
|
||||
System.out.println("*********************************************************************************");
|
||||
System.out.println("LEAKING THREADS");
|
||||
}
|
||||
failedThread = true;
|
||||
System.out.println("=============================================================================");
|
||||
System.out.println("Thread " + aliveThread + " is still alive with the following stackTrace:");
|
||||
StackTraceElement[] elements = postThreads.get(aliveThread);
|
||||
for (StackTraceElement el : elements) {
|
||||
System.out.println(el);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (failedThread) {
|
||||
System.out.println("*********************************************************************************");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return failedThread;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* if it's an expected thread... we will just move along ignoring it
|
||||
*
|
||||
* @param thread
|
||||
* @return
|
||||
*/
|
||||
private boolean isExpectedThread(Thread thread) {
|
||||
|
||||
for (String known: knownThreads) {
|
||||
if (thread.getName().contains(known)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
protected static class DumbReference {
|
||||
|
||||
private CountDownLatch finalized;
|
||||
|
||||
public DumbReference(CountDownLatch finalized) {
|
||||
this.finalized = finalized;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finalize() throws Throwable {
|
||||
finalized.countDown();
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.artemis.junit;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Utility adapted from: org.apache.activemq.util.Wait
|
||||
*/
|
||||
public class Wait {
|
||||
|
||||
public static final long MAX_WAIT_MILLIS = 30 * 1000;
|
||||
public static final int SLEEP_MILLIS = 1000;
|
||||
|
||||
public interface Condition {
|
||||
|
||||
boolean isSatisfied() throws Exception;
|
||||
}
|
||||
|
||||
public static boolean waitFor(Condition condition) throws Exception {
|
||||
return waitFor(condition, MAX_WAIT_MILLIS);
|
||||
}
|
||||
|
||||
public static boolean waitFor(final Condition condition, final long duration) throws Exception {
|
||||
return waitFor(condition, duration, SLEEP_MILLIS);
|
||||
}
|
||||
|
||||
public static boolean waitFor(final Condition condition,
|
||||
final long duration,
|
||||
final long sleepMillis) throws Exception {
|
||||
|
||||
final long expiry = System.currentTimeMillis() + duration;
|
||||
boolean conditionSatisified = condition.isSatisfied();
|
||||
while (!conditionSatisified && System.currentTimeMillis() < expiry) {
|
||||
TimeUnit.MILLISECONDS.sleep(sleepMillis);
|
||||
conditionSatisified = condition.isSatisfied();
|
||||
}
|
||||
return conditionSatisified;
|
||||
}
|
||||
|
||||
}
|
@ -50,14 +50,22 @@ public class ActiveMQConsumerResourceTest {
|
||||
|
||||
ActiveMQConsumerResource consumer = new ActiveMQConsumerResource(server.getVmURL(), TEST_QUEUE);
|
||||
|
||||
|
||||
@Rule
|
||||
public RuleChain ruleChain = RuleChain.outerRule(server).around(consumer);
|
||||
public RuleChain ruleChain = RuleChain.outerRule(new ThreadLeakCheckRule()).outerRule(server).around(consumer);
|
||||
|
||||
|
||||
ClientMessage sent = null;
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
assertNotNull(String.format(ASSERT_SENT_FORMAT, TEST_ADDRESS), sent);
|
||||
Wait.waitFor(new Wait.Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() throws Exception {
|
||||
return server.getMessageCount("TEST_QUEUE") == 1;
|
||||
}
|
||||
}, 5000, 100);
|
||||
assertEquals(String.format(ASSERT_COUNT_FORMAT, TEST_QUEUE), 1, server.getMessageCount(TEST_QUEUE));
|
||||
|
||||
ClientMessage received = consumer.receiveMessage();
|
||||
|
@ -51,7 +51,7 @@ public class ActiveMQDynamicProducerResourceTest {
|
||||
ActiveMQDynamicProducerResource producer = new ActiveMQDynamicProducerResource(server.getVmURL(), TEST_QUEUE_ONE);
|
||||
|
||||
@Rule
|
||||
public RuleChain ruleChain = RuleChain.outerRule(server).around(producer);
|
||||
public RuleChain ruleChain = RuleChain.outerRule(new ThreadLeakCheckRule()).around(server).around(producer);
|
||||
|
||||
ClientMessage sentOne = null;
|
||||
ClientMessage sentTwo = null;
|
||||
@ -60,6 +60,12 @@ public class ActiveMQDynamicProducerResourceTest {
|
||||
public void tearDown() throws Exception {
|
||||
assertNotNull(String.format(ASSERT_SENT_FORMAT, TEST_QUEUE_ONE), sentOne);
|
||||
assertNotNull(String.format(ASSERT_SENT_FORMAT, TEST_QUEUE_TWO), sentTwo);
|
||||
Wait.waitFor(new Wait.Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() throws Exception {
|
||||
return server.getMessageCount(TEST_QUEUE_ONE) == 1 && server.getMessageCount(TEST_QUEUE_TWO) == 1;
|
||||
}
|
||||
}, 5000, 100);
|
||||
assertEquals(String.format(ASSERT_COUNT_FORMAT, TEST_QUEUE_ONE), 1, server.getMessageCount(TEST_QUEUE_ONE));
|
||||
assertEquals(String.format(ASSERT_COUNT_FORMAT, TEST_QUEUE_TWO), 1, server.getMessageCount(TEST_QUEUE_TWO));
|
||||
|
||||
|
@ -43,7 +43,7 @@ public class ActiveMQDynamicProducerResourceWithoutAddressExceptionTest {
|
||||
ActiveMQDynamicProducerResource producer = new ActiveMQDynamicProducerResource(server.getVmURL());
|
||||
|
||||
@Rule
|
||||
public RuleChain ruleChain = RuleChain.outerRule(server).around(producer);
|
||||
public RuleChain ruleChain = RuleChain.outerRule(new ThreadLeakCheckRule()).around(server).around(producer);
|
||||
|
||||
ClientMessage sentOne = null;
|
||||
|
||||
|
@ -52,7 +52,7 @@ public class ActiveMQDynamicProducerResourceWithoutAddressTest {
|
||||
ActiveMQDynamicProducerResource producer = new ActiveMQDynamicProducerResource(server.getVmURL());
|
||||
|
||||
@Rule
|
||||
public RuleChain ruleChain = RuleChain.outerRule(server).around(producer);
|
||||
public RuleChain ruleChain = RuleChain.outerRule(new ThreadLeakCheckRule()).around(server).around(producer);
|
||||
|
||||
ClientMessage sentOne = null;
|
||||
ClientMessage sentTwo = null;
|
||||
@ -68,6 +68,12 @@ public class ActiveMQDynamicProducerResourceWithoutAddressTest {
|
||||
public void tearDown() throws Exception {
|
||||
assertNotNull(String.format(ASSERT_SENT_FORMAT, TEST_QUEUE_ONE), sentOne);
|
||||
assertNotNull(String.format(ASSERT_SENT_FORMAT, TEST_QUEUE_TWO), sentTwo);
|
||||
Wait.waitFor(new Wait.Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() throws Exception {
|
||||
return server.getMessageCount(TEST_QUEUE_ONE) == 1 && server.getMessageCount(TEST_QUEUE_TWO) == 1;
|
||||
}
|
||||
}, 5000, 100);
|
||||
assertEquals(String.format(ASSERT_COUNT_FORMAT, TEST_QUEUE_ONE), 1, server.getMessageCount(TEST_QUEUE_ONE));
|
||||
assertEquals(String.format(ASSERT_COUNT_FORMAT, TEST_QUEUE_TWO), 1, server.getMessageCount(TEST_QUEUE_TWO));
|
||||
|
||||
|
@ -50,7 +50,7 @@ public class ActiveMQProducerResourceTest {
|
||||
ActiveMQProducerResource producer = new ActiveMQProducerResource(server.getVmURL(), TEST_ADDRESS);
|
||||
|
||||
@Rule
|
||||
public RuleChain ruleChain = RuleChain.outerRule(server).around(producer);
|
||||
public RuleChain ruleChain = RuleChain.outerRule(new ThreadLeakCheckRule()).around(server).around(producer);
|
||||
|
||||
ClientMessage sent = null;
|
||||
|
||||
|
@ -24,6 +24,7 @@ import org.apache.activemq.artemis.core.config.impl.ConfigurationImpl;
|
||||
import org.apache.activemq.artemis.core.server.Queue;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.RuleChain;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
@ -37,8 +38,10 @@ public class EmbeddedActiveMQResourceCustomConfigurationTest {
|
||||
CoreQueueConfiguration queueConfiguration = new CoreQueueConfiguration().setAddress(TEST_ADDRESS).setName(TEST_QUEUE);
|
||||
Configuration customConfiguration = new ConfigurationImpl().setPersistenceEnabled(false).setSecurityEnabled(true).addQueueConfiguration(queueConfiguration);
|
||||
|
||||
private EmbeddedActiveMQResource server = new EmbeddedActiveMQResource(customConfiguration);
|
||||
|
||||
@Rule
|
||||
public EmbeddedActiveMQResource server = new EmbeddedActiveMQResource(customConfiguration);
|
||||
public RuleChain rulechain = RuleChain.outerRule(new ThreadLeakCheckRule()).around(server);
|
||||
|
||||
@Test
|
||||
public void testCustomConfiguration() throws Exception {
|
||||
|
@ -21,6 +21,7 @@ import java.util.List;
|
||||
import org.apache.activemq.artemis.core.server.Queue;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.RuleChain;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
@ -31,8 +32,11 @@ public class EmbeddedActiveMQResourceFileConfigurationTest {
|
||||
static final String TEST_QUEUE = "test.queue";
|
||||
static final String TEST_ADDRESS = "test.address";
|
||||
|
||||
private EmbeddedActiveMQResource server = new EmbeddedActiveMQResource("embedded-artemis-server.xml");
|
||||
|
||||
@Rule
|
||||
public EmbeddedActiveMQResource server = new EmbeddedActiveMQResource("embedded-artemis-server.xml");
|
||||
public RuleChain rulechain = RuleChain.outerRule(new ThreadLeakCheckRule()).around(server);
|
||||
|
||||
|
||||
@Test
|
||||
public void testConfiguredQueue() throws Exception {
|
||||
|
@ -25,6 +25,7 @@ import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.RuleChain;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
@ -46,9 +47,11 @@ public class EmbeddedActiveMQResourceTest {
|
||||
TEST_PROPERTIES.put("PropertyTwo", "Property Value 2");
|
||||
}
|
||||
|
||||
@Rule
|
||||
public EmbeddedActiveMQResource server = new EmbeddedActiveMQResource();
|
||||
|
||||
@Rule
|
||||
public RuleChain rulechain = RuleChain.outerRule(new ThreadLeakCheckRule()).around(server);
|
||||
|
||||
ClientMessage sent = null;
|
||||
|
||||
@Before
|
||||
@ -59,6 +62,12 @@ public class EmbeddedActiveMQResourceTest {
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
assertNotNull(String.format(ASSERT_SENT_FORMAT, TEST_ADDRESS), sent);
|
||||
Wait.waitFor(new Wait.Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() throws Exception {
|
||||
return server.getMessageCount(TEST_QUEUE) == 1;
|
||||
}
|
||||
}, 5000, 100);
|
||||
assertEquals(String.format(ASSERT_COUNT_FORMAT, TEST_QUEUE), 1, server.getMessageCount(TEST_QUEUE));
|
||||
|
||||
ClientMessage received = server.receiveMessage(TEST_QUEUE);
|
||||
|
@ -29,6 +29,7 @@ import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.RuleChain;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
@ -42,9 +43,11 @@ public class EmbeddedJMSResourceMultipleFileConfigurationTest {
|
||||
static final String ASSERT_PUSHED_FORMAT = "Message should have been pushed a message to %s";
|
||||
static final String ASSERT_COUNT_FORMAT = "Unexpected message count in destination %s";
|
||||
|
||||
@Rule
|
||||
public EmbeddedJMSResource jmsServer = new EmbeddedJMSResource("embedded-artemis-minimal-server.xml", "embedded-artemis-jms-only.xml");
|
||||
|
||||
@Rule
|
||||
public RuleChain rulechain = RuleChain.outerRule(new ThreadLeakCheckRule()).around(jmsServer);
|
||||
|
||||
ConnectionFactory connectionFactory;
|
||||
Connection connection;
|
||||
Session session;
|
||||
|
@ -24,6 +24,7 @@ import java.util.Map;
|
||||
import org.junit.After;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.RuleChain;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
@ -48,14 +49,22 @@ public class EmbeddedJMSResourceQueueTest {
|
||||
TEST_PROPERTIES.put("PropertyTwo", "Property Value 2");
|
||||
}
|
||||
|
||||
@Rule
|
||||
public EmbeddedJMSResource jmsServer = new EmbeddedJMSResource();
|
||||
|
||||
@Rule
|
||||
public RuleChain rulechain = RuleChain.outerRule(new ThreadLeakCheckRule()).around(jmsServer);
|
||||
|
||||
Message pushed = null;
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
assertNotNull(String.format(ASSERT_PUSHED_FORMAT, TEST_DESTINATION_NAME), pushed);
|
||||
Wait.waitFor(new Wait.Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() throws Exception {
|
||||
return jmsServer.getMessageCount(TEST_DESTINATION_NAME) == 1;
|
||||
}
|
||||
}, 5000, 100);
|
||||
assertEquals(String.format(ASSERT_COUNT_FORMAT, TEST_DESTINATION_NAME), 1, jmsServer.getMessageCount(TEST_DESTINATION_NAME));
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@ import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.RuleChain;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
@ -42,9 +43,11 @@ public class EmbeddedJMSResourceSingleFileConfigurationTest {
|
||||
static final String ASSERT_PUSHED_FORMAT = "Message should have been pushed a message to %s";
|
||||
static final String ASSERT_COUNT_FORMAT = "Unexpected message count in destination %s";
|
||||
|
||||
@Rule
|
||||
public EmbeddedJMSResource jmsServer = new EmbeddedJMSResource("embedded-artemis-jms-server.xml");
|
||||
|
||||
@Rule
|
||||
public RuleChain rulechain = RuleChain.outerRule(new ThreadLeakCheckRule()).around(jmsServer);
|
||||
|
||||
ConnectionFactory connectionFactory;
|
||||
Connection connection;
|
||||
Session session;
|
||||
|
@ -31,6 +31,7 @@ import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.RuleChain;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
@ -55,9 +56,11 @@ public class EmbeddedJMSResourceTopicTest {
|
||||
TEST_PROPERTIES.put("PropertyTwo", "Property Value 2");
|
||||
}
|
||||
|
||||
@Rule
|
||||
public EmbeddedJMSResource jmsServer = new EmbeddedJMSResource();
|
||||
|
||||
@Rule
|
||||
public RuleChain rulechain = RuleChain.outerRule(new ThreadLeakCheckRule()).around(jmsServer);
|
||||
|
||||
Message pushed = null;
|
||||
|
||||
ConnectionFactory connectionFactory;
|
||||
@ -77,6 +80,12 @@ public class EmbeddedJMSResourceTopicTest {
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
assertNotNull(String.format(ASSERT_PUSHED_FORMAT, TEST_DESTINATION_NAME), pushed);
|
||||
Wait.waitFor(new Wait.Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() throws Exception {
|
||||
return jmsServer.getMessageCount(TEST_DESTINATION_NAME) == 1;
|
||||
}
|
||||
}, 5000, 100);
|
||||
assertEquals(String.format(ASSERT_COUNT_FORMAT, TEST_DESTINATION_NAME), 1, jmsServer.getMessageCount(TEST_DESTINATION_NAME));
|
||||
|
||||
consumer.close();
|
||||
|
@ -21,6 +21,7 @@ import org.apache.activemq.artemis.api.core.client.ClientMessage;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.RuleChain;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
@ -37,12 +38,13 @@ public class MultipleEmbeddedActiveMQResourcesTest {
|
||||
static final String ASSERT_RECEIVED_FORMAT = "Message should have been received from %s";
|
||||
static final String ASSERT_COUNT_FORMAT = "Unexpected message count in queue %s";
|
||||
|
||||
@Rule
|
||||
public EmbeddedActiveMQResource serverOne = new EmbeddedActiveMQResource(0);
|
||||
|
||||
@Rule
|
||||
public EmbeddedActiveMQResource serverTwo = new EmbeddedActiveMQResource(1);
|
||||
|
||||
@Rule
|
||||
public RuleChain rulechain = RuleChain.outerRule(new ThreadLeakCheckRule()).around(serverOne).around(serverTwo);
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
serverOne.createQueue(TEST_ADDRESS_ONE, TEST_QUEUE_ONE);
|
||||
|
@ -20,6 +20,7 @@ import javax.jms.Message;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.RuleChain;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
@ -33,12 +34,13 @@ public class MultipleEmbeddedJMSResourcesTest {
|
||||
static final String ASSERT_PUSHED_FORMAT = "Message should have been pushed a message to %s";
|
||||
static final String ASSERT_COUNT_FORMAT = "Unexpected message count in destination %s";
|
||||
|
||||
@Rule
|
||||
public EmbeddedJMSResource jmsServerOne = new EmbeddedJMSResource(0);
|
||||
|
||||
@Rule
|
||||
public EmbeddedJMSResource jmsServerTwo = new EmbeddedJMSResource(1);
|
||||
|
||||
@Rule
|
||||
public RuleChain rulechain = RuleChain.outerRule(new ThreadLeakCheckRule()).around(jmsServerOne).around(jmsServerTwo);
|
||||
|
||||
@Test
|
||||
public void testMultipleServers() throws Exception {
|
||||
Message pushedOne = jmsServerOne.pushMessage(TEST_QUEUE_ONE, TEST_BODY);
|
||||
|
@ -56,6 +56,7 @@
|
||||
* [Protocols and Interoperability](protocols-interoperability.md)
|
||||
* [Tools](tools.md)
|
||||
* [Maven Plugin](maven-plugin.md)
|
||||
* [Unit Testing](unit-testing.md)
|
||||
* [Troubleshooting and Performance Tuning](perf-tuning.md)
|
||||
* [Configuration Reference](configuration-index.md)
|
||||
|
||||
|
77
docs/user-manual/en/unit-testing.md
Normal file
77
docs/user-manual/en/unit-testing.md
Normal file
@ -0,0 +1,77 @@
|
||||
# Unit Testing
|
||||
|
||||
The package ```artemis-junit``` provides tools to facilitate how to run Artemis resources inside Junit Tests.
|
||||
|
||||
These are provided as junit rules and can make it easier to embed Messaging functionality on your tests.
|
||||
|
||||
|
||||
## Example
|
||||
|
||||
|
||||
### Import this on your pom.xml
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>artemis-junit</artifactId>
|
||||
<!-- replace this for the version you are using -->
|
||||
<version>1.5.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
|
||||
### Declare a rule on your JUnit Test
|
||||
|
||||
|
||||
```java
|
||||
import org.apache.activemq.artemis.junit.EmbeddedJMSResource;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
public class MyTest {
|
||||
|
||||
@Rule
|
||||
public EmbeddedJMSResource resource = new EmbeddedJMSResource();
|
||||
|
||||
@Test
|
||||
public void myTest() {
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This will start a server that will be available for your test:
|
||||
|
||||
```
|
||||
ain] 17:00:16,644 INFO [org.apache.activemq.artemis.core.server] AMQ221000: live Message Broker is starting with configuration Broker Configuration (clustered=false,journalDirectory=data/journal,bindingsDirectory=data/bindings,largeMessagesDirectory=data/largemessages,pagingDirectory=data/paging)
|
||||
[main] 17:00:16,666 INFO [org.apache.activemq.artemis.core.server] AMQ221045: libaio is not available, switching the configuration into NIO
|
||||
[main] 17:00:16,688 INFO [org.apache.activemq.artemis.core.server] AMQ221043: Protocol module found: [artemis-server]. Adding protocol support for: CORE
|
||||
[main] 17:00:16,801 INFO [org.apache.activemq.artemis.core.server] AMQ221007: Server is now live
|
||||
[main] 17:00:16,801 INFO [org.apache.activemq.artemis.core.server] AMQ221001: Apache ActiveMQ Artemis Message Broker version 1.5.0-SNAPSHOT [embedded-jms-server, nodeID=39e78380-842c-11e6-9e43-f45c8992f3c7]
|
||||
[main] 17:00:16,891 INFO [org.apache.activemq.artemis.core.server] AMQ221002: Apache ActiveMQ Artemis Message Broker version 1.5.0-SNAPSHOT [39e78380-842c-11e6-9e43-f45c8992f3c7] stopped, uptime 0.272 seconds
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Ordering rules
|
||||
|
||||
This is actually a Junit feature, but this could be helpful on pre-determining the order on which rules are executed.
|
||||
|
||||
```java
|
||||
ActiveMQDynamicProducerResource producer = new ActiveMQDynamicProducerResource(server.getVmURL());
|
||||
|
||||
@Rule
|
||||
public RuleChain ruleChain = RuleChain.outerRule(new ThreadLeakCheckRule()).around(server).around(producer);
|
||||
|
||||
```
|
||||
|
||||
### Available Rules
|
||||
|
||||
Name | Description
|
||||
:--- | :---
|
||||
EmbeddedActiveMQResource | It will run a Server, without the JMS manager
|
||||
EmbeddedJMSResource | It will run a Server, including the JMS Manager
|
||||
ActiveMQConsumerResource | It will automate the creation of a consumer
|
||||
ActiveMQProducerResource | It will automate the creation of a producer
|
||||
ThreadLeakCheckRule | It will check that all threads have been finished after the test is finished
|
Loading…
x
Reference in New Issue
Block a user