<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<body link="#355491" alink="#4262a1" vlink="#355491" style="background: #e2e2e2; margin: 0; padding: 20px;">
<div>
        <table cellpadding="0" bgcolor="#FFFFFF" border="0" cellspacing="0" style="border: 1px solid #dadada; margin-bottom: 30px; width: 100%; -moz-border-radius: 6px; -webkit-border-radius: 6px;">
                <tbody>
                        <tr>
                                <td>
                                        <table border="0" cellpadding="0" cellspacing="0" bgcolor="#FFFFFF" style="border: solid 2px #ccc; background: #dadada; width: 100%; -moz-border-radius: 6px; -webkit-border-radius: 6px;">
                                                <tbody>
                                                        <tr>
                                                                <td bgcolor="#000000" valign="middle" height="58px" style="border-bottom: 1px solid #ccc; padding: 20px; -moz-border-radius-topleft: 3px; -moz-border-radius-topright: 3px; -webkit-border-top-right-radius: 5px; -webkit-border-top-left-radius: 5px;">
                                                                        <h1 style="color: #333333; font: bold 22px Arial, Helvetica, sans-serif; margin: 0; display: block !important;">
                                                                        <!-- To have a header image/logo replace the name below with your img tag -->
                                                                        <!-- Email clients will render the images when the message is read so any image -->
                                                                        <!-- must be made available on a public server, so that all recipients can load the image. -->
                                                                        <a href="http://community.jboss.org/index.jspa" style="text-decoration: none; color: #E1E1E1">JBoss Community</a></h1>
                                                                </td>
                                                        </tr>
                                                        <tr>
                                                                <td bgcolor="#FFFFFF" style="font: normal 12px Arial, Helvetica, sans-serif; color:#333333; padding: 20px; -moz-border-radius-bottomleft: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 5px; -webkit-border-bottom-left-radius: 5px;"><h3 style="margin: 10px 0 5px; font-size: 17px; font-weight: normal;">
JUnit test support for jBPM5
</h3>
<span style="margin-bottom: 10px;">
modified by <a href="http://community.jboss.org/people/swiderski.maciej">Maciej Swiderski</a> in <i>jBPM</i> - <a href="http://community.jboss.org/docs/DOC-17345">View the full document</a>
</span>
<hr style="margin: 20px 0; border: none; background-color: #dadada; height: 1px;">
<div class="jive-rendered-content"><p>There are number of issues that people are facing while working with jBPM and to get help the most useful elements are:</p><ul><li style="text-align: start;">process definition (BPMN2 file)</li><li style="text-align: start;">test case that illustrates mentioned issue</li></ul><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>As process definition is concerned that is rather straight forward (since we already working with it when encountering the problem),</p><p>but with test case it can be bit more complex to give directly to others the driver we use for our case.</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>So, after struggling for some time with exactly the same issue, I decided to start with small but yet powerful support for test cases for jBPM.</p><p>There is already a test case class that we could extend and that already brings some useful elements but that is not all we need...</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>I tried to build up a small library that is dedicated to test cases based on JUnit and that aligns with latest releases of JUnit, meaning it is </p><p>based on annotations. So to move directly what I am referring to, lets take a look at very simple test case:</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><pre class="jive-pre"><code class="jive-code jive-java">@RunWith(JbpmJUnitRunner.class)
@KnowledgeBase(source=<font color="navy">{</font><font color="red">"script.bpmn2"</font><font color="navy">}</font>)
@KnowledgeSession()
<font color="navy"><b>public</b></font> <font color="navy"><b>class</b></font> JbpmJUnitTestCase <font color="navy">{</font>
 
    <font color="navy"><b>protected</b></font> org.drools.KnowledgeBase knowledgeBase;
    <font color="navy"><b>protected</b></font> StatefulKnowledgeSession session;
 
    @Test
    <font color="navy"><b>public</b></font> <font color="navy"><b>void</b></font> testScriptTask() <font color="navy">{</font>
        ProcessInstance instance = session.startProcess(<font color="red">"ScriptTask"</font>);
        assertProcessInstanceComplete(instance);
    <font color="navy">}</font>
<font color="navy">}</font>
</code></pre><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>What you can see here is the most basic test case that allows to execute and assert process instance completion. I think the code is self explanatory so </p><p>I jump directly to the annotations that were introduced with this library:</p><p><em><strong>@RunWith</strong></em> - this one is standard JUnit annotation that instructs what runner should be used to execute tests</p><p><em><strong>@KnowledgeBase</strong></em> - annotation that defines what artifacts should be loaded into knowledge base </p><p>    Annotation attributes:</p><ul><li style="text-align: start;">    source - list of resources to be loaded (currently only BPMN2 resources are supported)</li><li style="text-align: start;">    sharedKey - name of the key that will be used to cache knowledge based between test cases, so if you have set of resources that are used across various</li></ul><p>                test cases and you want to avoid building knowledge base for each of the test cases sharedKey attribute should be set to load knowledge base only one time</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p><em><strong>@KnowledgeSession</strong></em> - annotation that defines how stateful sessions should be created and maintained</p><p>    Annotation attributes:</p><ul><li style="text-align: start;">    disposePerTest - defines if session should be disposed after each test within test case, default set to true</li><li style="text-align: start;">    logger - defines what working memory logger should be configured for the session, available options NONE (default), CONSOLE, JPA</li><li style="text-align: start;">    handlers - set of work item handlers that will be registered for each session (WorkItemHandler annotation)</li><li style="text-align: start;">    persistence - defines persistence for the session (Persistence annotation)</li></ul><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>        <em><strong>@Persistence</strong></em> annotation attributes:</p><ul><li style="text-align: start;">    persistenceUnit - name of the persistence unit that should be used while configuring JPA entity manager factory</li><li style="text-align: start;">    reloadSession - defines if session should be reloaded (with the same id) between test invocation within test case, default false</li></ul><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>        <em><strong>@WorkItemHandler</strong></em> annotation attributes:</p><ul><li style="text-align: start;">     taskName - name of the task the handler is registered for</li><li style="text-align: start;">     handles - class of the handler</li></ul><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p><em><strong>@HumanTaskSupport</strong></em> - annotation that instructs runner that test case requires Human Task interactions so it will initialize Task Server accessible via MINA transport</p><p>            it will be started on test case scope, meaning that all tests will have access to the same instance of the server within test case.</p><p>            Annotation attributes:</p><ul><li style="text-align: start;">            users - list of user ids that should be added to the task server on startup</li><li style="text-align: start;">            groups - list of groups that should be added to the task server on startup</li><li style="text-align: start;">            persistanceUnit - name of the persistence unit that should be used while building entity manager factory</li><li style="text-align: start;">            host - interface on which task server should be started, defaults to localhost</li><li style="text-align: start;">            port - port on which task server should be started, defaults to 9123</li></ul><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>In addition to annotation there are two property files required when configuring session persistence or human task server:</p><ul><li style="text-align: start;">datasource.properties - defines parameters of connection pool</li><li style="text-align: start;">jndi.properties - defines JNDI provider for bitronix</li></ul><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>NOTE: Connection pool will be created for entire test phase once datasource.properties file was discovered.</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>Obviously following files are required as well, since they are required by jbpm and task server artifacts:</p><ul><li style="text-align: start;">META-INF/persistence.xml that defines both (jbpm and human task persistence units)</li><li style="text-align: start;">META-INF/JBPMorm.xml </li><li style="text-align: start;">META-INF/Taskorm.xml</li></ul><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>Main concept is around injecting dependencies into your test case class. As dependencies I mean following items:</p><ul><li style="text-align: start;">Knowledge base</li><li style="text-align: start;">Stateful session</li><li style="text-align: start;">Task client</li></ul><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>Methods from JUnit life cycle are still available, such as these annotated with @Before, @After, @BeforeClass, @AfterClass. Instance methods (@Before @After) will</p><p>have access to session and knowledge base, for instance if some facts should be inserted before running the test.</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>There is one more item that is worth to mention, an assert class dedicated to jbpm - JbpmAssert, which defines (at the moment):</p><ul><li style="text-align: start;">assertProcessInstanceComplete</li><li style="text-align: start;">assertProcessInstanceActive</li><li style="text-align: start;">assertProcessInstanceAborted</li><li style="text-align: start;">assertProcessInstancePending</li><li style="text-align: start;">assertProcessInstanceSuspended</li></ul><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>and most likely more to come...</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p><strong>And now, its time to show some examples of it</strong></p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>Simple test case with session persistence:</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><pre class="jive-pre"><code class="jive-code jive-java">@RunWith(JbpmJUnitRunner.class)
@KnowledgeBase(source=<font color="navy">{</font><font color="red">"script.bpmn2"</font><font color="navy">}</font>)
@KnowledgeSession(persistence=@Persistence(persistenceUnit=<font color="red">"org.jbpm.persistence.jpa"</font>))
<font color="navy"><b>public</b></font> <font color="navy"><b>class</b></font> JbpmJUnitTestCase <font color="navy">{</font>
 
    <font color="navy"><b>protected</b></font> org.drools.KnowledgeBase knowledgeBase;
    <font color="navy"><b>protected</b></font> StatefulKnowledgeSession session;
 
    @Test
    <font color="navy"><b>public</b></font> <font color="navy"><b>void</b></font> testScriptTask() <font color="navy">{</font>
        ProcessInstance instance = session.startProcess(<font color="red">"ScriptTask"</font>);
        assertProcessInstanceComplete(instance);
    <font color="navy">}</font>
<font color="navy">}</font>
</code></pre><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>If session reload is desired between tests test case should be defined as follows:</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><pre class="jive-pre"><code class="jive-code jive-java">@RunWith(JbpmJUnitRunner.class)
@KnowledgeBase(source=<font color="navy">{</font><font color="red">"script.bpmn2"</font><font color="navy">}</font>)
@KnowledgeSession(persistence=@Persistence(persistenceUnit=<font color="red">"org.jbpm.persistence.jpa"</font>, reloadSession=<font color="navy"><b>true</b></font>))
<font color="navy"><b>public</b></font> <font color="navy"><b>class</b></font> JbpmJUnitTestCase <font color="navy">{</font>
 
    <font color="navy"><b>protected</b></font> org.drools.KnowledgeBase knowledgeBase;
    <font color="navy"><b>protected</b></font> StatefulKnowledgeSession session;
 
    @Test
    <font color="navy"><b>public</b></font> <font color="navy"><b>void</b></font> testScriptTask() <font color="navy">{</font>
        ProcessInstance instance = session.startProcess(<font color="red">"ScriptTask"</font>);
        assertProcessInstanceComplete(instance);
    <font color="navy">}</font>
    @Test
    <font color="navy"><b>public</b></font> <font color="navy"><b>void</b></font> testScriptTask2() <font color="navy">{</font>
        ProcessInstance instance = session.startProcess(<font color="red">"ScriptTask"</font>);
        assertProcessInstanceComplete(instance);
    <font color="navy">}</font>
<font color="navy">}</font>
</code></pre><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>Both tests will use same session.</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>Last but not least, human interaction test case:</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><pre class="jive-pre"><code class="jive-code jive-java">@RunWith(JbpmJUnitRunner.class)
@KnowledgeBase(source=<font color="navy">{</font><font color="red">"script.bpmn2"</font>,<font color="red">"usertask.bpmn2"</font><font color="navy">}</font>, sharedKey=<font color="red">"common"</font>)
@KnowledgeSession(handlers=<font color="navy">{</font>@WorkItemHandler(taskName=<font color="red">"Human Task"</font>, handler=WSHumanTaskHandler.class)<font color="navy">}</font>, logger=Logger.CONSOLE)
@HumanTaskSupport(persistenceUnit=<font color="red">"org.jbpm.task"</font>, users=<font color="navy">{</font><font color="red">"john"</font>, <font color="red">"Administrator"</font><font color="navy">}</font>)
<font color="navy"><b>public</b></font> <font color="navy"><b>class</b></font> JbpmJUnitRunnerTest <font color="navy">{</font>
 
    <font color="navy"><b>protected</b></font> org.drools.KnowledgeBase knowledgeBase;
    <font color="navy"><b>protected</b></font> StatefulKnowledgeSession session;
    <font color="navy"><b>protected</b></font> TaskClient taskClient;
 
    @Test
    <font color="navy"><b>public</b></font> <font color="navy"><b>void</b></font> testHumanTask() <font color="navy"><b>throws</b></font> Exception <font color="navy">{</font>
        ProcessInstance instance = session.startProcess(<font color="red">"UserTask"</font>);
        Thread.sleep(1000);
        BlockingTaskSummaryResponseHandler taskSummaryHandler = <font color="navy"><b>new</b></font> BlockingTaskSummaryResponseHandler();
        taskClient.getTasksAssignedAsPotentialOwner(<font color="red">"john"</font>, <font color="red">"en-UK"</font>, taskSummaryHandler);
 
        assertEquals(1, taskSummaryHandler.getResults().size());
        TaskSummary task1 = taskSummaryHandler.getResults().get(0);
 
        BlockingTaskOperationResponseHandler taskOperationHandler = <font color="navy"><b>new</b></font> BlockingTaskOperationResponseHandler();
        taskClient.claim(task1.getId(), <font color="red">"john"</font>, taskOperationHandler);
 
        taskOperationHandler = <font color="navy"><b>new</b></font> BlockingTaskOperationResponseHandler();
        taskClient.start(task1.getId(), <font color="red">"john"</font>, taskOperationHandler);
        taskOperationHandler.waitTillDone(1000);
 
        taskOperationHandler = <font color="navy"><b>new</b></font> BlockingTaskOperationResponseHandler();
        taskClient.complete(task1.getId(), <font color="red">"john"</font>, null, taskOperationHandler);
        taskOperationHandler.waitTillDone(1000);
 
        Thread.sleep(1000);
 
        assertProcessInstanceComplete(instance);
    <font color="navy">}</font>
<font color="navy">}</font>
</code></pre><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>In the example we can notice several configurations elements:</p><ul><li style="text-align: start;">knowledge base is configured to be shared between test cases under 'common' shared key</li><li style="text-align: start;">knowledge session will have registered handler for 'Human Task' work items</li><li style="text-align: start;">knowledge session will have a console logger configured</li><li style="text-align: start;">human task server will be configured with 'org.jbpm.task' persistence unit and will add two users once it's started (john, Administrator)</li></ul><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>Ok, so that is it! I hope you can provide some feedback about it and hopefully we can get a valuable discussion around it and what's even more important</p><p>maybe we start using it on daily basis so everybody could benefit from it.</p><p>Attached draft version of the library.</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>Looking forward to your comments</p></div>
<div style="background-color: #f4f4f4; padding: 10px; margin-top: 20px;">
<p style="margin: 0;">Comment by <a href="http://community.jboss.org/docs/DOC-17345">going to Community</a></p>
        <p style="margin: 0;">Create a new document in jBPM at <a href="http://community.jboss.org/choose-container!input.jspa?contentType=102&containerType=14&container=2034">Community</a></p>
</div></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>