blob: 80d0f624f8e6025a8e039ba114adc3ceffbed453 [file] [log] [blame]
/*
* 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.camel;
import java.util.Map;
import javax.naming.Context;
import org.apache.camel.builder.NotifyBuilder;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.impl.DefaultCamelContext;
import org.apache.camel.impl.JndiRegistry;
import org.apache.camel.model.ModelCamelContext;
import org.apache.camel.spi.Language;
import org.apache.camel.support.jndi.JndiTest;
import org.junit.After;
import org.junit.Before;
/**
* A useful base class which creates a {@link CamelContext} with some routes
* along with a {@link ProducerTemplate} for use in the test case
*/
public abstract class ContextTestSupport extends TestSupport {
protected volatile ModelCamelContext context;
protected volatile ProducerTemplate template;
protected volatile ConsumerTemplate consumer;
protected volatile NotifyBuilder oneExchangeDone;
private boolean useRouteBuilder = true;
private Service camelContextService;
/**
* Use the RouteBuilder or not
*
* @return If the return value is true, the camel context will be started in
* the setup method. If the return value is false, the camel context
* will not be started in the setup method.
*/
public boolean isUseRouteBuilder() {
return useRouteBuilder;
}
public void setUseRouteBuilder(boolean useRouteBuilder) {
this.useRouteBuilder = useRouteBuilder;
}
public Service getCamelContextService() {
return camelContextService;
}
/**
* Allows a service to be registered a separate lifecycle service to start
* and stop the context; such as for Spring when the ApplicationContext is
* started and stopped, rather than directly stopping the CamelContext
*/
public void setCamelContextService(Service camelContextService) {
this.camelContextService = camelContextService;
}
/**
* Convenient api to create a NotifyBuilder to be notified of a specific
* event
*/
protected NotifyBuilder event() {
return new NotifyBuilder(context);
}
@Override
@Before
public void setUp() throws Exception {
super.setUp();
// make SEDA testing faster
System.setProperty("CamelSedaPollTimeout", "10");
CamelContext c2 = createCamelContext();
if (c2 instanceof ModelCamelContext) {
context = (ModelCamelContext)c2;
} else {
throw new Exception("Context must be a ModelCamelContext");
}
assertValidContext(context);
context.init();
// reduce default shutdown timeout to avoid waiting for 300 seconds
context.getShutdownStrategy().setTimeout(10);
template = context.createProducerTemplate();
template.start();
consumer = context.createConsumerTemplate();
consumer.start();
// create a default notifier when 1 exchange is done which is the most
// common case
oneExchangeDone = event().whenDone(1).create();
if (isUseRouteBuilder()) {
RouteBuilder[] builders = createRouteBuilders();
for (RouteBuilder builder : builders) {
log.debug("Using created route builder: {}", builder);
context.addRoutes(builder);
}
startCamelContext();
} else {
log.debug("isUseRouteBuilder() is false");
}
}
@Override
@After
public void tearDown() throws Exception {
log.debug("tearDown test: {}", getName());
if (consumer != null) {
consumer.stop();
}
if (template != null) {
template.stop();
}
stopCamelContext();
System.clearProperty("CamelSedaPollTimeout");
super.tearDown();
}
/**
* Whether or not JMX should be used during testing.
*
* @return <tt>false</tt> by default.
*/
protected boolean useJmx() {
return false;
}
/**
* Whether to load additional type converters by scanning the classpath.
* This should only be enabled for tests that uses custom type converters.
*/
protected boolean isLoadTypeConverters() {
return true;
}
protected void stopCamelContext() throws Exception {
if (camelContextService != null) {
camelContextService.stop();
} else {
if (context != null) {
context.stop();
}
}
}
protected void startCamelContext() throws Exception {
if (camelContextService != null) {
camelContextService.start();
} else {
if (context instanceof DefaultCamelContext) {
DefaultCamelContext defaultCamelContext = (DefaultCamelContext)context;
if (!defaultCamelContext.isStarted()) {
defaultCamelContext.start();
}
} else {
context.start();
}
}
}
protected CamelContext createCamelContext() throws Exception {
DefaultCamelContext context = new DefaultCamelContext(false);
if (!useJmx()) {
context.disableJMX();
}
context.setRegistry(createRegistry());
context.setLoadTypeConverters(isLoadTypeConverters());
return context;
}
protected JndiRegistry createRegistry() throws Exception {
return new JndiRegistry(createJndiContext());
}
protected Context createJndiContext() throws Exception {
return JndiTest.createInitialContext();
}
/**
* Factory method which derived classes can use to create a
* {@link RouteBuilder} to define the routes for testing
*/
protected RouteBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
public void configure() {
// no routes added by default
}
};
}
/**
* Factory method which derived classes can use to create an array of
* {@link RouteBuilder}s to define the routes for testing
*
* @see #createRouteBuilder()
*/
protected RouteBuilder[] createRouteBuilders() throws Exception {
return new RouteBuilder[] {createRouteBuilder()};
}
/**
* Resolves a mandatory endpoint for the given URI or an exception is thrown
*
* @param uri the Camel <a href="">URI</a> to use to create or resolve an
* endpoint
* @return the endpoint
*/
protected Endpoint resolveMandatoryEndpoint(String uri) {
return resolveMandatoryEndpoint(context, uri);
}
/**
* Resolves a mandatory endpoint for the given URI and expected type or an
* exception is thrown
*
* @param uri the Camel <a href="">URI</a> to use to create or resolve an
* endpoint
* @return the endpoint
*/
protected <T extends Endpoint> T resolveMandatoryEndpoint(String uri, Class<T> endpointType) {
return resolveMandatoryEndpoint(context, uri, endpointType);
}
/**
* Resolves the mandatory Mock endpoint using a URI of the form
* <code>mock:someName</code>
*
* @param uri the URI which typically starts with "mock:" and has some name
* @return the mandatory mock endpoint or an exception is thrown if it could
* not be resolved
*/
protected MockEndpoint getMockEndpoint(String uri) {
return resolveMandatoryEndpoint(uri, MockEndpoint.class);
}
/**
* Sends a message to the given endpoint URI with the body value
*
* @param endpointUri the URI of the endpoint to send to
* @param body the body for the message
*/
protected void sendBody(String endpointUri, final Object body) {
template.send(endpointUri, new Processor() {
public void process(Exchange exchange) {
Message in = exchange.getIn();
in.setBody(body);
in.setHeader("testCase", getName());
}
});
}
/**
* Sends a message to the given endpoint URI with the body value and
* specified headers
*
* @param endpointUri the URI of the endpoint to send to
* @param body the body for the message
* @param headers any headers to set on the message
*/
protected void sendBody(String endpointUri, final Object body, final Map<String, Object> headers) {
template.send(endpointUri, new Processor() {
public void process(Exchange exchange) {
Message in = exchange.getIn();
in.setBody(body);
in.setHeader("testCase", getName());
for (Map.Entry<String, Object> entry : headers.entrySet()) {
in.setHeader(entry.getKey(), entry.getValue());
}
}
});
}
/**
* Sends messages to the given endpoint for each of the specified bodies
*
* @param endpointUri the endpoint URI to send to
* @param bodies the bodies to send, one per message
*/
protected void sendBodies(String endpointUri, Object... bodies) {
for (Object body : bodies) {
sendBody(endpointUri, body);
}
}
/**
* Creates an exchange with the given body
*/
protected Exchange createExchangeWithBody(Object body) {
return createExchangeWithBody(context, body);
}
/**
* Asserts that the given language name and expression evaluates to the
* given value on a specific exchange
*/
protected void assertExpression(Exchange exchange, String languageName, String expressionText, Object expectedValue) {
Language language = assertResolveLanguage(languageName);
Expression expression = language.createExpression(expressionText);
assertNotNull("No Expression could be created for text: " + expressionText + " language: " + language, expression);
assertExpression(expression, exchange, expectedValue);
}
/**
* Asserts that the given language name and predicate expression evaluates
* to the expected value on the message exchange
*/
protected void assertPredicate(String languageName, String expressionText, Exchange exchange, boolean expected) {
Language language = assertResolveLanguage(languageName);
Predicate predicate = language.createPredicate(expressionText);
assertNotNull("No Predicate could be created for text: " + expressionText + " language: " + language, predicate);
assertPredicate(predicate, exchange, expected);
}
/**
* Asserts that the language name can be resolved
*/
protected Language assertResolveLanguage(String languageName) {
Language language = context.resolveLanguage(languageName);
assertNotNull("No language found for name: " + languageName, language);
return language;
}
/**
* Asserts that all the expectations of the Mock endpoints are valid
*/
protected void assertMockEndpointsSatisfied() throws InterruptedException {
MockEndpoint.assertIsSatisfied(context);
}
/**
* Sets the assert period on all the Mock endpoints
*/
protected void setAssertPeriod(long period) {
MockEndpoint.setAssertPeriod(context, period);
}
/**
* Reset all Mock endpoints.
*/
protected void resetMocks() {
MockEndpoint.resetMocks(context);
}
protected void assertValidContext(CamelContext context) {
assertNotNull("No context found!", context);
}
protected <T extends Endpoint> T getMandatoryEndpoint(String uri, Class<T> type) {
T endpoint = context.getEndpoint(uri, type);
assertNotNull("No endpoint found for uri: " + uri, endpoint);
return endpoint;
}
protected Endpoint getMandatoryEndpoint(String uri) {
Endpoint endpoint = context.getEndpoint(uri);
assertNotNull("No endpoint found for uri: " + uri, endpoint);
return endpoint;
}
}