camel-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache Camel > Camel Test
Date Sat, 08 Sep 2012 09:43:00 GMT
<html>
<head>
    <base href="https://cwiki.apache.org/confluence">
            <link rel="stylesheet" href="/confluence/s/2042/9/1/_/styles/combined.css?spaceKey=CAMEL&amp;forWysiwyg=true"
type="text/css">
    </head>
<body style="background: white;" bgcolor="white" class="email-body">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
    <h2><a href="https://cwiki.apache.org/confluence/display/CAMEL/Camel+Test">Camel
Test</a></h2>
    <h4>Page <b>edited</b> by             <a href="https://cwiki.apache.org/confluence/display/~muellerc">Christian
Mueller</a>
    </h4>
        <br/>
                         <h4>Changes (1)</h4>
                                 
    
<div id="page-diffs">
                    <table class="diff" cellpadding="0" cellspacing="0">
    
            <tr><td class="diff-unchanged" >h2. Camel Test <br> <br></td></tr>
            <tr><td class="diff-changed-lines" >As a simple alternative to using
[Spring Testing] or [Guice] the *camel-test* module was introduced <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">into
the Camel 2.0 trunk</span> so you can perform powerful [Testing] of your [Enterprise
Integration Patterns] easily. <br></td></tr>
            <tr><td class="diff-unchanged" > <br>{info:tile=JUnit or TestNG}
<br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
    
            </table>
    </div>                            <h4>Full Content</h4>
                    <div class="notificationGreySide">
        <h2><a name="CamelTest-CamelTest"></a>Camel Test</h2>

<p>As a simple alternative to using <a href="/confluence/display/CAMEL/Spring+Testing"
title="Spring Testing">Spring Testing</a> or <a href="/confluence/display/CAMEL/Guice"
title="Guice">Guice</a> the <b>camel-test</b> module was introduced so
you can perform powerful <a href="/confluence/display/CAMEL/Testing" title="Testing">Testing</a>
of your <a href="/confluence/display/CAMEL/Enterprise+Integration+Patterns" title="Enterprise
Integration Patterns">Enterprise Integration Patterns</a> easily.</p>

<div class='panelMacro'><table class='infoMacro'><colgroup><col width='24'><col></colgroup><tr><td
valign='top'><img src="/confluence/images/icons/emoticons/information.gif" width="16"
height="16" align="absmiddle" alt="" border="0"></td><td>The <tt>camel-test</tt>
JAR is using JUnit. There is an alternative <tt>camel-testng</tt> JAR (Camel 2.8
onwards) using the <a href="http://testng.org/doc/index.html" class="external-link" rel="nofollow">TestNG</a>
test framework.</td></tr></table></div>

<h3><a name="CamelTest-Addingtoyourpom.xml"></a>Adding to your pom.xml</h3>

<p>To get started using Camel Test you will need to add an entry to your pom.xml</p>

<h4><a name="CamelTest-JUnit"></a>JUnit</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
<span class="code-tag">&lt;dependency&gt;</span>
  <span class="code-tag">&lt;groupId&gt;</span>org.apache.camel<span
class="code-tag">&lt;/groupId&gt;</span>
  <span class="code-tag">&lt;artifactId&gt;</span>camel-test<span class="code-tag">&lt;/artifactId&gt;</span>
  <span class="code-tag">&lt;version&gt;</span>${camel-version}<span
class="code-tag">&lt;/version&gt;</span>
  <span class="code-tag">&lt;scope&gt;</span>test<span class="code-tag">&lt;/scope&gt;</span>
<span class="code-tag">&lt;/dependency&gt;</span>
</pre>
</div></div>

<h4><a name="CamelTest-TestNG"></a>TestNG</h4>

<p><b>Available as of Camel 2.8</b></p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
<span class="code-tag">&lt;dependency&gt;</span>
  <span class="code-tag">&lt;groupId&gt;</span>org.apache.camel<span
class="code-tag">&lt;/groupId&gt;</span>
  <span class="code-tag">&lt;artifactId&gt;</span>camel-testng<span
class="code-tag">&lt;/artifactId&gt;</span>
  <span class="code-tag">&lt;version&gt;</span>${camel-version}<span
class="code-tag">&lt;/version&gt;</span>
  <span class="code-tag">&lt;scope&gt;</span>test<span class="code-tag">&lt;/scope&gt;</span>
<span class="code-tag">&lt;/dependency&gt;</span>
</pre>
</div></div>

<p>You might also want to add slf4j and log4j to ensure nice logging messages (and maybe
adding a <a href="http://svn.apache.org/repos/asf/camel/trunk/components/camel-test/src/test/resources/log4j.properties"
class="external-link" rel="nofollow">log4j.properties</a> file into your src/test/resources
directory).</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
<span class="code-tag">&lt;dependency&gt;</span>
  <span class="code-tag">&lt;groupId&gt;</span>org.slf4j<span class="code-tag">&lt;/groupId&gt;</span>
  <span class="code-tag">&lt;artifactId&gt;</span>slf4j-log4j12<span
class="code-tag">&lt;/artifactId&gt;</span>
  <span class="code-tag">&lt;scope&gt;</span>test<span class="code-tag">&lt;/scope&gt;</span>
<span class="code-tag">&lt;/dependency&gt;</span>
<span class="code-tag">&lt;dependency&gt;</span>
  <span class="code-tag">&lt;groupId&gt;</span>log4j<span class="code-tag">&lt;/groupId&gt;</span>
  <span class="code-tag">&lt;artifactId&gt;</span>log4j<span class="code-tag">&lt;/artifactId&gt;</span>
  <span class="code-tag">&lt;scope&gt;</span>test<span class="code-tag">&lt;/scope&gt;</span>
<span class="code-tag">&lt;/dependency&gt;</span>
</pre>
</div></div>

<h3><a name="CamelTest-Writingyourtest"></a>Writing your test</h3>

<p>You firstly need to derive from the class <b>CamelTestSupport</b>&nbsp;(org.apache.camel.test.CamelTestSupport,
org.apache.camel.test.junit4.CamelTestSupport, or org.apache.camel.testng.CamelTestSupport
for JUnit 3.x, JUnit 4.x, and TestNG, respectively)&nbsp;and typically you will need to
override the <b>createRouteBuilder()</b> or&nbsp;<b>createRouteBuilders()</b>&nbsp;method
to create routes to be tested.</p>

<p>Here is an <a href="http://svn.apache.org/repos/asf/camel/trunk/components/camel-test/src/test/java/org/apache/camel/test/patterns/FilterTest.java"
class="external-link" rel="nofollow">example</a>.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">public</span> class FilterTest
<span class="code-keyword">extends</span> CamelTestSupport {

    @EndpointInject(uri = <span class="code-quote">"mock:result"</span>)
    <span class="code-keyword">protected</span> MockEndpoint resultEndpoint;

    @Produce(uri = <span class="code-quote">"direct:start"</span>)
    <span class="code-keyword">protected</span> ProducerTemplate template;

    @Test
    <span class="code-keyword">public</span> void testSendMatchingMessage() <span
class="code-keyword">throws</span> Exception {
        <span class="code-object">String</span> expectedBody = <span class="code-quote">"&lt;matched/&gt;"</span>;

        resultEndpoint.expectedBodiesReceived(expectedBody);

        template.sendBodyAndHeader(expectedBody, <span class="code-quote">"foo"</span>,
<span class="code-quote">"bar"</span>);

        resultEndpoint.assertIsSatisfied();
    }

    @Test
    <span class="code-keyword">public</span> void testSendNotMatchingMessage()
<span class="code-keyword">throws</span> Exception {
        resultEndpoint.expectedMessageCount(0);

        template.sendBodyAndHeader(<span class="code-quote">"&lt;notMatched/&gt;"</span>,
<span class="code-quote">"foo"</span>, <span class="code-quote">"notMatchedHeaderValue"</span>);

        resultEndpoint.assertIsSatisfied();
    }

    @Override
    <span class="code-keyword">protected</span> RouteBuilder createRouteBuilder()
{
        <span class="code-keyword">return</span> <span class="code-keyword">new</span>
RouteBuilder() {
            <span class="code-keyword">public</span> void configure() {
                from(<span class="code-quote">"direct:start"</span>).filter(header(<span
class="code-quote">"foo"</span>).isEqualTo(<span class="code-quote">"bar"</span>)).to(<span
class="code-quote">"mock:result"</span>);
            }
        };
    }
}
</pre>
</div></div>

<p>Notice how you can use the various <a href="/confluence/display/CAMEL/Bean+Integration"
title="Bean Integration">Camel binding and injection annotations</a> to inject individual
<a href="/confluence/display/CAMEL/Endpoint" title="Endpoint">Endpoint</a> objects
- particularly the <a href="/confluence/display/CAMEL/Mock" title="Mock">Mock endpoints</a>
which are very useful for <a href="/confluence/display/CAMEL/Testing" title="Testing">Testing</a>.
Also you can inject <a href="/confluence/display/CAMEL/POJO+Producing" title="POJO Producing">producer
objects such as ProducerTemplate or some application code interface</a> for sending
messages or invoking services.</p>

<h4><a name="CamelTest-FeaturesProvidedbyCamelTestSupport"></a>Features
Provided by CamelTestSupport</h4>

<p>The various <b>CamelTestSupport</b> classes provide a standard set of
behaviors relating to the CamelContext used to host the route(s) under test. &nbsp;The
classes provide a number of methods that allow a test to alter the configuration of the CamelContext
used. &nbsp;The following table describes the available customization methods and the
default behavior of tests that are built from a&nbsp;<b>CamelTestSupport</b>
class.</p>
<div class='table-wrap'>
<table class='confluenceTable'><tbody>
<tr>
<th class='confluenceTh'> Method Name </th>
<th class='confluenceTh'> Description </th>
<th class='confluenceTh'> Default Behavior </th>
</tr>
<tr>
<td class='confluenceTd'> boolean isUseRouteBuilder() </td>
<td class='confluenceTd'> If the route builders from returned from&nbsp;<b>createRouteBuilder()</b>
or <b>createRouteBuilders()</b> should be added to the CamelContext used in the
test should be started. </td>
<td class='confluenceTd'> Returns true. &nbsp;<b>createRouteBuilder()</b>&nbsp;or&nbsp;<b>createRouteBuilders()</b>
are invoked and the CamelContext is started automatically. </td>
</tr>
<tr>
<td class='confluenceTd'> boolean isUseAdviceWith() <br class="atl-forced-newline"
/> </td>
<td class='confluenceTd'> If the CamelContext use in the test should be automatically
started before test methods are invoked. <br class="atl-forced-newline" />
Override when using <a href="/confluence/display/CAMEL/AdviceWith" title="AdviceWith">advice
with</a>&nbsp;and return true. &nbsp;This helps in knowing the adviceWith is
to be used, and the&nbsp;CamelContext&nbsp;will not be started before&nbsp;the
advice with takes place. This delay helps by ensuring the advice with has been property setup
before the&nbsp;CamelContext&nbsp;is started.
<div class='panelMacro'><table class='infoMacro'><colgroup><col width='24'><col></colgroup><tr><td
valign='top'><img src="/confluence/images/icons/emoticons/information.gif" width="16"
height="16" align="absmiddle" alt="" border="0"></td><td>Its important to start
the CamelContext manually from the unit test after you are done doing all the advice with.</td></tr></table></div>
<p><br class="atl-forced-newline" /> </p></td>
<td class='confluenceTd'> Returns false. &nbsp;the CamelContext is started automatically
before test methods are invoked. </td>
</tr>
<tr>
<td class='confluenceTd'> boolean isCreateCamelContextPerClass() <br class="atl-forced-newline"
/> </td>
<td class='confluenceTd'> See&nbsp;<a href="#CamelTest-SetupCamelContextonceperclass%2Corpereverytestmethod">Setup
CamelContext once per class, or per every test method</a>. </td>
<td class='confluenceTd'> The CamelContext and routes are recreated for each test method.
</td>
</tr>
<tr>
<td class='confluenceTd'> String isMockEndpoints() </td>
<td class='confluenceTd'> Triggers the auto-mocking of endpoints whose URIs match the
provided filter. &nbsp;The default&nbsp;filter is null which disables this feature.
&nbsp;Return "*" &nbsp;to match all endpoints. &nbsp;See&nbsp;org.apache.camel.impl.InterceptSendToMockEndpointStrategy&nbsp;for&nbsp;more
details on the registration of the mock endpoints. </td>
<td class='confluenceTd'> Disabled </td>
</tr>
<tr>
<td class='confluenceTd'> boolean isUseDebugger() </td>
<td class='confluenceTd'> If this method returns true, the&nbsp;<b>debugBefore(Exchange
exchange, Processor processor, ProcessorDefinition&lt;?&gt; definition,&nbsp;String
id, String label)</b>&nbsp;and&nbsp;<br class="atl-forced-newline" />
<b>debugAfter(Exchange exchange, Processor processor, ProcessorDefinition&lt;?&gt;
definition,&nbsp;String id, String label, long timeTaken)</b>&nbsp;methods are
invoked for each processor in the registered routes. </td>
<td class='confluenceTd'> Disabled. &nbsp;The methods are not invoked during the
test. </td>
</tr>
<tr>
<td class='confluenceTd'> int getShutdownTimeout() </td>
<td class='confluenceTd'> Returns the number of seconds that Camel should wait for graceful
shutdown. &nbsp;Useful for decreasing test times when a message is still in flight at
the end of the test. </td>
<td class='confluenceTd'> Returns 10 seconds. </td>
</tr>
<tr>
<td class='confluenceTd'> boolean useJmx() </td>
<td class='confluenceTd'> If JMX should be disabled on the CamelContext used in the
test. </td>
<td class='confluenceTd'> JMX is disabled. </td>
</tr>
<tr>
<td class='confluenceTd'> JndiRegistry createRegistry() <br class="atl-forced-newline"
/> </td>
<td class='confluenceTd'> Provides a hook for adding objects into the registry. &nbsp;Override
this method to bind objects to the registry before test methods are invoked. </td>
<td class='confluenceTd'> An empty registry is initialized. </td>
</tr>
</tbody></table>
</div>



<h3><a name="CamelTest-JNDI"></a>JNDI</h3>

<p>Camel uses a <a href="/confluence/display/CAMEL/Registry" title="Registry">Registry</a>
to allow you to configure <a href="/confluence/display/CAMEL/Component" title="Component">Component</a>
or <a href="/confluence/display/CAMEL/Endpoint" title="Endpoint">Endpoint</a>
instances or <a href="/confluence/display/CAMEL/Bean+Integration" title="Bean Integration">Beans
used in your routes</a>. If you are not using <a href="/confluence/display/CAMEL/Spring"
title="Spring">Spring</a> or <a href="/confluence/pages/createpage.action?spaceKey=CAMEL&amp;title=OSGi&amp;linkCreation=true&amp;fromPageId=104074"
class="createlink">OSGi</a> then <a href="/confluence/display/CAMEL/JNDI" title="JNDI">JNDI</a>
is used as the default registry implementation.</p>

<p>So you will also need to create a <b>jndi.properties</b> file in your
<b>src/test/resources</b> directory so that there is a default registry available
to initialise the <a href="/confluence/display/CAMEL/CamelContext" title="CamelContext">CamelContext</a>.</p>

<p>Here is <a href="http://svn.apache.org/repos/asf/camel/trunk/components/camel-test/src/test/resources/jndi.properties"
class="external-link" rel="nofollow">an example jndi.properties file</a></p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
java.naming.factory.initial = org.apache.camel.util.jndi.CamelInitialContextFactory
</pre>
</div></div>

<h3><a name="CamelTest-Dynamicallyassigningports"></a>Dynamically assigning
ports</h3>

<p><b>Available as of Camel 2.7</b></p>

<p>Tests that use port numbers will fail if that port is already on use. <tt>AvailablePortFinder</tt>
provides methods for finding unused port numbers at runtime.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
<span class="code-comment">// Get the next available port number starting from the <span
class="code-keyword">default</span> starting port of 1024
</span><span class="code-object">int</span> port1 = AvailablePortFinder.getNextAvailable();
/*
 * Get another port. Note that just getting a port number does not reserve it so
 * we look starting one past the last port number we got.
 */
<span class="code-object">int</span> port2 = AvailablePortFinder.getNextAvailable(port1
+ 1);
</pre>
</div></div>


<h3><a name="CamelTest-SetupCamelContextonceperclass%2Corpereverytestmethod"></a>Setup
CamelContext once per class, or per every test method</h3>

<p><b>Available as of Camel 2.8</b></p>

<p>The <a href="/confluence/display/CAMEL/Camel+Test" title="Camel Test">Camel
Test</a> kit will by default setup and shutdown <a href="/confluence/display/CAMEL/CamelContext"
title="CamelContext">CamelContext</a> per every test method in your test class. So
for example if you have 3 test methods, then <a href="/confluence/display/CAMEL/CamelContext"
title="CamelContext">CamelContext</a> is started and shutdown after each test, that
is 3 times.</p>

<div class='panelMacro'><table class='tipMacro'><colgroup><col width='24'><col></colgroup><tr><td
valign='top'><img src="/confluence/images/icons/emoticons/check.gif" width="16" height="16"
align="absmiddle" alt="" border="0"></td><td><b>TestNG</b><br
/>This feature is also supported in camel-testng</td></tr></table></div>

<div class='panelMacro'><table class='warningMacro'><colgroup><col width='24'><col></colgroup><tr><td
valign='top'><img src="/confluence/images/icons/emoticons/forbidden.gif" width="16"
height="16" align="absmiddle" alt="" border="0"></td><td><b>Beware</b><br
/>When using this the <a href="/confluence/display/CAMEL/CamelContext" title="CamelContext">CamelContext</a>
will keep state between tests, so have that in mind. So if your unit tests start to fail for
no apparent reason, it could be due this fact. So use this feature with a bit of care.</td></tr></table></div>

<p>You may want to do this once, to share the <a href="/confluence/display/CAMEL/CamelContext"
title="CamelContext">CamelContext</a> between test methods, to speedup unit testing.
This requires to use JUnit 4&#33; In your unit test method you have to extend the <tt>org.apache.camel.test.junit4.CamelTestSupport</tt>
or the <tt>org.apache.camel.test.junit4.CamelSpringTestSupport</tt> test class
and override the <tt>isCreateCamelContextPerClass</tt> method and return <tt>true</tt>
as shown in the following example:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader"
style="border-bottom-width: 1px;"><b>Setup CamelContext once per class</b></div><div
class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">public</span> class FilterCreateCamelContextPerClassTest
<span class="code-keyword">extends</span> CamelTestSupport {

    @Override
    <span class="code-keyword">public</span> <span class="code-object">boolean</span>
isCreateCamelContextPerClass() {
        <span class="code-comment">// we override <span class="code-keyword">this</span>
method and <span class="code-keyword">return</span> <span class="code-keyword">true</span>,
to tell Camel test-kit that
</span>        <span class="code-comment">// it should only create CamelContext
once (per class), so we will
</span>        <span class="code-comment">// re-use the CamelContext between each
test method in <span class="code-keyword">this</span> class
</span>        <span class="code-keyword">return</span> <span class="code-keyword">true</span>;
    }

    @Test
    <span class="code-keyword">public</span> void testSendMatchingMessage() <span
class="code-keyword">throws</span> Exception {
        <span class="code-object">String</span> expectedBody = <span class="code-quote">"&lt;matched/&gt;"</span>;

        getMockEndpoint(<span class="code-quote">"mock:result"</span>).expectedBodiesReceived(expectedBody);

        template.sendBodyAndHeader(<span class="code-quote">"direct:start"</span>,
expectedBody, <span class="code-quote">"foo"</span>, <span class="code-quote">"bar"</span>);

        assertMockEndpointsSatisfied();
    }

    @Test
    <span class="code-keyword">public</span> void testSendNotMatchingMessage()
<span class="code-keyword">throws</span> Exception {
        getMockEndpoint(<span class="code-quote">"mock:result"</span>).expectedMessageCount(0);

        template.sendBodyAndHeader(<span class="code-quote">"direct:start"</span>,
<span class="code-quote">"&lt;notMatched/&gt;"</span>, <span class="code-quote">"foo"</span>,
<span class="code-quote">"notMatchedHeaderValue"</span>);

        assertMockEndpointsSatisfied();
    }

    @Override
    <span class="code-keyword">protected</span> RouteBuilder createRouteBuilder()
{
        <span class="code-keyword">return</span> <span class="code-keyword">new</span>
RouteBuilder() {
            <span class="code-keyword">public</span> void configure() {
                from(<span class="code-quote">"direct:start"</span>).filter(header(<span
class="code-quote">"foo"</span>).isEqualTo(<span class="code-quote">"bar"</span>)).to(<span
class="code-quote">"mock:result"</span>);
            }
        };
    }
}
</pre>
</div></div>


<h3><a name="CamelTest-SeeAlso"></a>See Also</h3>

<ul>
	<li><a href="/confluence/display/CAMEL/Testing" title="Testing">Testing</a></li>
	<li><a href="/confluence/display/CAMEL/Mock" title="Mock">Mock</a></li>
	<li><a href="/confluence/display/CAMEL/Test" title="Test">Test</a></li>
</ul>

    </div>
        <div id="commentsSection" class="wiki-content pageSection">
        <div style="float: right;">
            <a href="https://cwiki.apache.org/confluence/users/viewnotifications.action"
class="grey">Change Notification Preferences</a>
        </div>
        <a href="https://cwiki.apache.org/confluence/display/CAMEL/Camel+Test">View
Online</a>
        |
        <a href="https://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=104074&revisedVersion=16&originalVersion=15">View
Changes</a>
                |
        <a href="https://cwiki.apache.org/confluence/display/CAMEL/Camel+Test?showComments=true&amp;showCommentArea=true#addcomment">Add
Comment</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message