Nav

Run and Wait Scope

Functionality

The Run and Wait scope provided by MUnit allows you to instruct MUnit to wait until all asynchronous executions have completed. Hence, test execution does not start until all threads opened by production code have finished processing.

One consideration to have if you are using Maven:

You need to add the MUnit Synchronize module artifact to your pom file:


              
           
1
2
3
4
5
6
<!-- Synchronize Scope Dependency -->
<dependency>
          <groupId>com.mulesoft.munit.utils</groupId>
          <artifactId>munit-synchronize-module</artifactId>
          <version>1.0.0</version>
</dependency>

If you choose to mavenize your project, Studio will notify you that the Synchronize module dependency will be added.

Defining Run and Wait

In some cases, your production code may launch threads that produce key results. Usually, these are the results that you want to validate. But if those results are being processed in a separate thread, your test runs and finishes before that separate thread completes, that is, before the results that you want to validate are available. To avoid this problem, you can use the run-and-wait scope.

For the purposes of this document, we assume that we are testing the following Mule code:

run-and-wait-thread-sleep


    
            
         
1
2
3
4
5
6
7
&lt;flow name="exampleFlow"&gt;
  &lt;async&gt;
      &lt;expression-component&gt;
          Thread.sleep(3000);
      &lt;/expression-component&gt;
  &lt;/async&gt;
&lt;/flow&gt;

The goal is to make your test wait until the exampleFlow has finished. To do so, implement the test as shown below.

run-and-wait-flow-ref

  1. Define run-and-wait scope.

  2. Call the actual production code to test.


    
            
         
1
2
3
4
5
&lt;flow name="testFlow"&gt;
    &lt;synchronize:run-and-wait timeout="16000"&gt; <i class="conum" data-value="1"></i><b>(1)</b>
        &lt;flow-ref name="exampleFlow"/&gt; <i class="conum" data-value="2"></i><b>(2)</b>
    &lt;/synchronize:run-and-wait&gt;
&lt;/flow&gt;

<1> Define run-and-wait scope. <2> Call the actual production code to test.

Attribute Name Description

timeout

Defines the time (in milliseconds) to wait for all the threads to complete.

runAsync

Boolean. When runAsync is set to true, the synchronize module copies the triggering MuleEvent and sets its messageexchangepattern automatically to ONE_WAY, menaing that your MUnit test handles your Mule application’s requests using a ONE_WAY messaging style.
This allows your test suite to take the events triggered by the Mule application and put them in a SEDA queue. The callee thread returns and the message is processed by the SEDA thread pool.

Using this tool is the only way to run an MUnit test on Mule batch jobs.

Defining Run and Wait With Java Code

Java API usage

To define the run-and-wait scope in Java, you need to implement the Synchronizer abstract class:


          
       
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import org.mule.construct.Flow;
import org.mule.Synchronizer;
import org.mule.api.MuleEvent;

public class TheTest extends FunctionalMunitSuite {

  @Test
  public void test() throws Exception{
    final Flow flow = (Flow) muleContext.getRegistry().
      lookupFlowConstruct("testFlow");   (1)

    Synchronizer synchronizer =
      new Synchronizer(muleContext, 12000){  (2)

        @Override
        protected MuleEvent process(MuleEvent event) throws Exception{

            return flow.process(event);  (3)
        }
    };

    MuleEvent event = testEvent("payload");
    synchronizer.runAndWait(event);   (4)
  }
}
1 Obtain the flow to test.
2 Create a new Synchronizer and implement the abstract method process.
3 Usually what you want to do is run a flow.
4 Call the Synchronizer implementation defined in Note #2.