All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.mats3.test.abstractunit.AbstractMatsTest Maven / Gradle / Ivy

Go to download

Mats^3 Testing tools, as well as the base for specific JUnit or Jupiter (Junit 5) tools.

The newest version!
package io.mats3.test.abstractunit;

import java.util.concurrent.CopyOnWriteArrayList;

import javax.jms.ConnectionFactory;
import javax.sql.DataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.mats3.MatsEndpoint.ProcessTerminatorLambda;
import io.mats3.MatsFactory;
import io.mats3.MatsFactory.MatsPlugin;
import io.mats3.MatsInitiator;
import io.mats3.impl.jms.JmsMatsFactory;
import io.mats3.serial.MatsSerializer;
import io.mats3.test.MatsTestBrokerInterface;
import io.mats3.test.MatsTestFactory;
import io.mats3.test.MatsTestLatch;
import io.mats3.test.TestH2DataSource;
import io.mats3.test.broker.MatsTestBroker;
import io.mats3.util.MatsFuturizer;

/**
 * Base class containing common code for Rule_Mats and Extension_Mats located in the following modules:
 * 
    *
  • mats-test-junit
  • *
  • mats-test-jupiter
  • *
* This class sets up an in-vm Active MQ broker through the use of {@link MatsTestBroker} which is again utilized to * create the {@link MatsFactory} which can be utilized to create unit tests which rely on testing functionality * utilizing MATS. *

* The setup and creation of these objects are located in the {@link #beforeAll()} method, this method should be called * through the use JUnit and Jupiters life cycle methods. * * @author Endre Stølsvik - 2015 - http://endre.stolsvik.com * @author Kevin Mc Tiernan, 2020-10-18, [email protected] */ public abstract class AbstractMatsTest { protected static final Logger log = LoggerFactory.getLogger(AbstractMatsTest.class); protected MatsSerializer _matsSerializer; protected DataSource _dataSource; protected MatsTestBroker _matsTestBroker; protected MatsFactory _matsFactory; protected CopyOnWriteArrayList _createdMatsFactories = new CopyOnWriteArrayList<>(); // :: Lazy init: protected MatsInitiator _matsInitiator; protected MatsTestLatch _matsTestLatch; protected MatsFuturizer _matsFuturizer; protected MatsTestBrokerInterface _matsTestBrokerInterface; protected AbstractMatsTest(MatsSerializer matsSerializer) { _matsSerializer = matsSerializer; } protected AbstractMatsTest(MatsSerializer matsSerializer, DataSource dataSource) { _matsSerializer = matsSerializer; _dataSource = dataSource; } /** * Creates an in-vm ActiveMQ Broker which again is utilized to create a {@link JmsMatsFactory}. *

* This method should be called as a result of the following life cycle events for either JUnit or Jupiter: *

    *
  • BeforeClass - JUnit - static ClassRule
  • *
  • BeforeAllCallback - Jupiter - static Extension
  • *
*/ public void beforeAll() { log.debug("+++ JUnit/Jupiter +++ BEFORE_CLASS on ClassRule/Extension '" + id(getClass()) + "', JMS and MATS:"); // ::: ActiveMQ BrokerService and ConnectionFactory // ================================================== _matsTestBroker = MatsTestBroker.create(); // ::: MatsFactory // ================================================== log.debug("Setting up JmsMatsFactory."); // Allow for override in specialization classes, in particular the one with DB. _matsFactory = createMatsFactory(); log.debug("--- JUnit/Jupiter --- BEFORE_CLASS done on ClassRule/Extension '" + id(getClass()) + "', JMS and MATS."); } /** * Tear down method, stopping all {@link MatsFactory} created during a test setup and close the AMQ broker. *

* This method should be called as a result of the following life cycle events for either JUnit or Jupiter: *

    *
  • AfterClass - JUnit - static ClassRule
  • *
  • AfterAllCallback - Jupiter - static Extension
  • *
*/ public void afterAll() { log.info("+++ JUnit/Jupiter +++ AFTER_CLASS on ClassRule/Extension '" + id(getClass()) + "':"); // :: Close the MatsFuturizer if we've made it if (_matsFuturizer != null) { _matsFuturizer.close(); } // :: Close all MatsFactories (thereby closing all endpoints and initiators, and thus their connections). for (MatsFactory createdMatsFactory : _createdMatsFactories) { createdMatsFactory.stop(30_000); } // :: Close the Broker _matsTestBroker.close(); // :: If the DataSource is a TestH2DataSource, then close that if (_dataSource instanceof TestH2DataSource) { ((TestH2DataSource) _dataSource).close(); } // :: Clean up all possibly created "sub pieces" of this. The reason is that if this is put as a @ClassRule // on a super class of multiple tests, then this instance will be re-used upon the next test class's run // (the next class that extends the "base test class" that contains the static @ClassRule). // NOTE: NOT doing that for H2 DataSource, as we cannot recreate that here, and instead rely on it re-starting. _matsTestBroker = null; _matsFactory = null; _matsInitiator = null; _matsTestLatch = null; _matsFuturizer = null; _matsTestBrokerInterface = null; log.info("--- JUnit/Jupiter --- AFTER_CLASS done on ClassRule/Extension '" + id(getClass()) + "' DONE."); } /** * @return the default {@link MatsInitiator} from this rule's {@link MatsFactory}. */ public synchronized MatsInitiator getMatsInitiator() { if (_matsInitiator == null) { _matsInitiator = getMatsFactory().getDefaultInitiator(); } return _matsInitiator; } /** * @return a singleton {@link MatsTestLatch} */ public synchronized MatsTestLatch getMatsTestLatch() { if (_matsTestLatch == null) { _matsTestLatch = new MatsTestLatch(); } return _matsTestLatch; } /** * @return a convenience singleton {@link MatsFuturizer} created with this rule's {@link MatsFactory}. */ public synchronized MatsFuturizer getMatsFuturizer() { if (_matsFuturizer == null) { _matsFuturizer = MatsFuturizer.createMatsFuturizer(_matsFactory, "UnitTestingFuturizer"); } return _matsFuturizer; } /** * @return a {@link MatsTestBrokerInterface} instance for getting DLQs (and hopefully other snacks at a later time). */ public synchronized MatsTestBrokerInterface getMatsTestBrokerInterface() { if (_matsTestBrokerInterface == null) { _matsTestBrokerInterface = MatsTestBrokerInterface .create(_matsTestBroker.getConnectionFactory(), _matsFactory); } return _matsTestBrokerInterface; } /** * @return the JMS ConnectionFactory that this JUnit Rule sets up. */ public ConnectionFactory getJmsConnectionFactory() { return _matsTestBroker.getConnectionFactory(); } /** * @return the {@link MatsFactory} that this JUnit Rule sets up. */ public MatsFactory getMatsFactory() { return _matsFactory; } /** * You should probably NOT use this method, but instead the {@link #getMatsFactory()}!. *

* This method is public for a single reason: If you need a new, separate {@link MatsFactory} using the same * JMS ConnectionFactory as the one provided by {@link #getMatsFactory()}. The only currently known reason for this * is if you want to register two endpoints with the same endpointId, and the only reason for this again is to test * {@link MatsFactory#subscriptionTerminator(String, Class, Class, ProcessTerminatorLambda) * subscriptionTerminators}. * * @return a new, separate {@link MatsFactory} in addition to the one provided by {@link #getMatsFactory()}. */ public MatsFactory createMatsFactory() { // We handle life cycling in the Rule, so we don't need the auto-closing feature of the MatsTestFactory. MatsFactory matsFactory = MatsTestFactory.createWithBroker(_matsTestBroker, _matsSerializer, _dataSource); // Add it to the list of created MatsFactories. _createdMatsFactories.add(matsFactory); return matsFactory; } /** * @return the DataSource if this Rule/Extension was created with one, throws {@link IllegalStateException} * otherwise. * @throws IllegalStateException * if this Rule/Extension wasn't created with a DataSource. */ public DataSource getDataSource() { if (_dataSource == null) { throw new IllegalStateException("This " + this.getClass().getSimpleName() + " was not created with a DataSource, use the 'createWithDb' factory methods."); } return _dataSource; } /** * Loops through all the {@link MatsFactory}s contained in this Rule (default + any specifically created), and * removes all Endpoints and unknown Plugins from each of them, this ensures that all factories are "clean". *

* You may want to utilize this if you have multiple tests in a class, and set up the Endpoints using a @Before type * annotation in the test, as opposed to @BeforeClass. This because otherwise you will on the second test try to * create the endpoints one more time, and they will already exist, thus you'll get an Exception from the * MatsFactory. Another scenario is that you have a bunch of @Test methods, which inside the test sets up an * endpoint in the "Arrange" section. If you employ the same endpointId for each of those setups (that is, inside * the @Test method itself), you will get "duplicate endpoint" (which is good, as your test would probably randomly * fail anyhow). Thus, in such a scenario, as the first statement of each test, before creating the endpoint(s), * invoke this method. */ public void cleanMatsFactories() { // :: Since removing all endpoints will destroy the MatsFuturizer if it is made, we'll first close that synchronized (this) { // ?: Have we made the MatsFuturizer? if (_matsFuturizer != null) { // -> Yes, so close and null it. _matsFuturizer.close(); _matsFuturizer = null; } } // :: Loop through all created MATS factories and remove the endpoints and unknown plugins for (MatsFactory createdMatsFactory : _createdMatsFactories) { // .. Removing Endpoints createdMatsFactory.getEndpoints() .forEach(matsEndpoint -> matsEndpoint.remove(30_000)); // .. Removing unknown Plugins for (MatsPlugin plugin : createdMatsFactory.getFactoryConfig().getPlugins(MatsPlugin.class)) { // ?: Is this the standard MatsMetricsLoggingInterceptor? if (plugin.getClass().getSimpleName().equals("MatsMetricsLoggingInterceptor")) { // -> Yes, so don't remove it. continue; } // ?: Is this the standard MatsMicrometerInterceptor? if (plugin.getClass().getSimpleName().equals("MatsMicrometerInterceptor")) { // -> Yes, so don't remove it. continue; } // E-> No, none of the standard, so remove it. createdMatsFactory.getFactoryConfig().removePlugin(plugin); } } } protected String id(Class clazz) { return clazz.getSimpleName() + "@" + Integer.toHexString(System.identityHashCode(this)); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy