18°

聊聊artemis对junit的支持

本文主要研究一下artemis对junit的支持

TestRule

junit-4.12-sources.jar!/org/junit/rules/TestRule.java

public interface TestRule {
    /**
     * Modifies the method-running {@link Statement} to implement this
     * test-running rule.
     *
     * @param base The {@link Statement} to be modified
     * @param description A {@link Description} of the test implemented in {@code base}
     * @return a new statement, which may be the same as {@code base},
     *         a wrapper around {@code base}, or a completely new Statement.
     */
    Statement apply(Statement base, Description description);
}
  • TestRule定义了apply方法用于修改并返回Statement

ExternalResource

junit-4.12-sources.jar!/org/junit/rules/ExternalResource.java

public abstract class ExternalResource implements TestRule {
    public Statement apply(Statement base, Description description) {
        return statement(base);
    }
private Statement statement(final Statement base) {
    return new Statement() {
        @Override
        public void evaluate() throws Throwable {
            before();
            try {
                base.evaluate();
            } finally {
                after();
            }
        }
    };
}

/**
 * Override to set up your specific external resource.
 *
 * @throws Throwable if setup fails (which will disable {@code after}
 */
protected void before() throws Throwable {
    // do nothing
}

/**
 * Override to tear down your specific external resource.
 */
protected void after() {
    // do nothing
}

}

  • ExternalResource声明实现了TestRule接口,其apply方法创建一个匿名Statement并重写其evaluate方法,该方法先执行before,在执行base.evaluate(),最后执行after

EmbeddedActiveMQResource

activemq-artemis-2.11.0/artemis-junit/src/main/java/org/apache/activemq/artemis/junit/EmbeddedActiveMQResource.java

public class EmbeddedActiveMQResource extends ExternalResource {
//......

/** * Invoked by JUnit to setup the resource - start the embedded ActiveMQ Artemis server */ @Override protected void before() throws Throwable { log.info("Starting {}: {}", this.getClass().getSimpleName(), getServerName());

  this.start();

  super.before();

}

/** * Invoked by JUnit to tear down the resource - stops the embedded ActiveMQ Artemis server */ @Override protected void after() { log.info("Stopping {}: {}", this.getClass().getSimpleName(), getServerName());

  this.stop();

  super.after();

}

public void start() { try { server.start(); } catch (Exception ex) { throw new RuntimeException(String.format("Exception encountered starting %s: %s", server.getClass().getName(), this.getServerName()), ex); }

  configuration = server.getActiveMQServer().getConfiguration();

}

public void stop() { if (internalClient != null) { internalClient.stop(); internalClient = null; }

  if (server != null) {
     try {
        server.stop();
     } catch (Exception ex) {
        log.warn(String.format("Exception encountered stopping %s: %s", server.getClass().getSimpleName(), this.getServerName()), ex);
     }
  }

}

//......

}

  • EmbeddedActiveMQResource继承了ExternalResource,并覆盖了before及after方法;before执行的是start方法,after执行的是stop方法;start方法主要是执行EmbeddedActiveMQ.start;stop方法主要是执行InternalClient.stop以及EmbeddedActiveMQ.stop

AbstractActiveMQClientResource

activemq-artemis-2.11.0/artemis-junit/src/main/java/org/apache/activemq/artemis/junit/AbstractActiveMQClientResource.java

public abstract class AbstractActiveMQClientResource extends ExternalResource {
//......

@Override protected void before() throws Throwable { super.before(); start(); }

@Override protected void after() { stop(); super.after(); }

void start() { log.info("Starting {}", this.getClass().getSimpleName()); try { sessionFactory = serverLocator.createSessionFactory(); session = sessionFactory.createSession(username, password, false, true, true, serverLocator.isPreAcknowledge(), serverLocator.getAckBatchSize()); } catch (RuntimeException runtimeEx) { throw runtimeEx; } catch (Exception ex) { throw new ActiveMQClientResourceException(String.format("%s initialisation failure", this.getClass().getSimpleName()), ex); }

  createClient();

  try {
     session.start();
  } catch (ActiveMQException amqEx) {
     throw new ActiveMQClientResourceException(String.format("%s startup failure", this.getClass().getSimpleName()), amqEx);
  }

}

void stop() { stopClient(); if (session != null) { try { session.close(); } catch (ActiveMQException amqEx) { log.warn("ActiveMQException encountered closing InternalClient ClientSession - ignoring", amqEx); } finally { session = null; } } if (sessionFactory != null) { sessionFactory.close(); sessionFactory = null; } if (serverLocator != null) { serverLocator.close(); serverLocator = null; }

}

protected abstract void createClient();

protected abstract void stopClient();

//......

}

  • AbstractActiveMQClientResource继承了ExternalResource,其before方法执行的是start方法,其after方法执行的是stop方法;start方法会创建session,执行createClient,最后执行session.start;stop方法执行stopClient、session.close、sessionFactory.close、serverLocator.close;它定义了createClient、stopClient抽象方法需要子类去实现

ActiveMQProducerResource

activemq-artemis-2.11.0/artemis-junit/src/main/java/org/apache/activemq/artemis/junit/ActiveMQProducerResource.java

public class ActiveMQProducerResource extends AbstractActiveMQClientResource {
//......

@Override protected void createClient() { try { if (!session.addressQuery(address).isExists() && autoCreateQueue) { log.warn("{}: queue does not exist - creating queue: address = {}, name = {}", this.getClass().getSimpleName(), address.toString(), address.toString()); session.createQueue(address, address); } producer = session.createProducer(address); } catch (ActiveMQException amqEx) { throw new ActiveMQClientResourceException(String.format("Error creating producer for address %s", address.toString()), amqEx); } }

@Override protected void stopClient() { if (producer != null) { try { producer.close(); } catch (ActiveMQException amqEx) { log.warn("ActiveMQException encountered closing InternalClient ClientProducer - ignoring", amqEx); } finally { producer = null; } } }

//......

}

  • ActiveMQProducerResource继承了AbstractActiveMQClientResource;其createClient方法执行session.createProducer(address);其stopClient方法执行producer.close()

ActiveMQConsumerResource

activemq-artemis-2.11.0/artemis-junit/src/main/java/org/apache/activemq/artemis/junit/ActiveMQConsumerResource.java

public class ActiveMQConsumerResource extends AbstractActiveMQClientResource {
//......

@Override protected void createClient() { boolean browseOnly = false; try { if (!session.queueQuery(queueName).isExists() && autoCreateQueue) { log.warn("{}: queue does not exist - creating queue: address = {}, name = {}", this.getClass().getSimpleName(), queueName.toString(), queueName.toString()); session.createAddress(queueName, RoutingType.MULTICAST, true); session.createQueue(queueName, queueName); } consumer = session.createConsumer(queueName, browseOnly); } catch (ActiveMQException amqEx) { throw new ActiveMQClientResourceException(String.format("Error creating consumer for queueName %s", queueName.toString()), amqEx); } }

@Override protected void stopClient() { if (consumer != null) { try { consumer.close(); } catch (ActiveMQException amqEx) { log.warn("Exception encountered closing consumer - ignoring", amqEx); } finally { consumer = null; } } }

//......

}

  • ActiveMQConsumerResource继承了AbstractActiveMQClientResource,其createClient方法执行的是session.createConsumer(queueName, browseOnly);其stopClient方法执行的是consumer.close()

小结

artemis对junit的ExternalResource提供了扩展,对于server端提供了EmbeddedActiveMQResource,对于client端提供了AbstractActiveMQClientResource(ActiveMQProducerResource、ActiveMQConsumerResource)

doc

本文由【go4it】发布于开源中国,原文链接:https://my.oschina.net/go4it/blog/3160130

全部评论: 0

    我有话说: