Nav
You are viewing an older version of this section. Click here to navigate to the latest version.

MUnit Suite

This page and related MUnit pages are focused on XML; however, MUnit is fully compatible with Anypoint Studio’s graphical user interface. Within the Studio environment, you can create, design and run MUnit tests just like you would Mule applications. You can even use Studio’s Visual Debugger to debug your MUnit tests. For an overview of MUnit in Studio, see Using MUnit in Anypoint Studio.

Definition

The base of the MUnit Framework consists of MUnit Test Suite files. These files are the .xml files located under the src/test/munit folder in your Mule application’s folder structure. Each MUnit Test Suite file is a collection of MUnit tests. It is meant to work on its own, and should be able to run independently from any other MUnit test suite files.

Components of an MUnit Test Suite

An MUnit test suite file should contain any combination of the following components:

  • Imports

  • Bean Definitions

  • Before/After Suites

  • Before/After Tests

  • MUnit Tests

Each MUnit test suite file is, behind the scenes, no different than a Mule application XML file. You can use several of the Mule top level elements such as flow, sub-flow, scripts, etc.

Defining Imports

Each MUnit suite is meant to test a particular set of Mule flows. To do that, you need to tell MUnit where those flows are defined in your application structure. For this we use imports, which are in fact spring imports.

Note: MUnit does not support Mule Domains.

Spring Import Example

         
      
1
2
3
<spring:beans>
  <spring:import resource="classpath:your-production-code.xml"/>
</spring:beans>
If your application is spread across multiple files and the components in those files cross-reference each other, you need to import all of the files.
Currently, MUnit Suite doesn’t support the use of components defined in Shared Resources. It’s required to define those components explicitly in the test suit file in order to execute the test.
Ideally, your production code and your flows should be arranged in a cohesive way — this improves readability, maintainability and testability.

Defining Before and After Suites

As with other testing frameworks, MUnit provides certain features around the test suite concept. In particular, you can add processing/actions to be run before and/or after the entire MUnit Test Suite executions.

Defining a Before Suite

The MUnit Before Suite is a scope. It can contain code that is meant to be executed before the whole suite.

For instance, let’s suppose you have an MUnit Test Suite file with four tests. The code inside an MUnit Before Suite runs just once, before your four tests.

The MUnit Before Suite is a top level scope, so you can have as many Before Suites as you need. They all follow the same execution rule: Run before the tests, just once.

If there is more than one Before Suite, MUnit does not guarantee the order in which the Before Suites run amongst themselves.
Before Suite example

          
       
1
2
3
<munit:before-suite name="before.suite" description="A description">
  <!-- some mule code here --> (1)
</munit:before-suite >
1 Define the code you want to run
Attribute Name Description

name

Defines the name of the Before suite. The name must be unique inside the suite.

description

Describes the actions performed.

One instance in which the MUnit Before Suite is useful is when you need to set up a test environment before the whole test runs.

Defining an After Suite

The MUnit After Suite is a scope. It can contain code that is meant to be executed after the whole suite.

For instance, let’s suppose you have an MUnit Test Suite File with four tests. The code inside an MUnit After Suite, runs just once, after all your tests.

The MUnit After Suite is a top level scope, thus you can have as many After Suites as you need. They all follow the same execution rule: Run after the tests, just once.

If there is more than one After Suite, MUnit does not guarantee the order in which the After Suites run amongst themselves.
After Suite example

          
       
1
2
3
<munit:after-suite  name="after.suite" description="A description">
  <!-- some Mule code here --> (1)
</munit:after-suite >
1 Define the code you want to run
Attribute Name Description

name

Defines the name of the After suite. The name must be unique inside the suite.

description

Describes the actions performed.

One instance in which the MUnit After Suite is useful is when you need to set up a test environment after the whole test runs.

Defining Before and After Tests

MUnit provides the ability to perform Before and After tests. These are similar to the concepts defined by JUnit. You can add processing/actions to be run before and/or after the execution of each MUnit Test suite.

Defining a Before Test

The MUnit Before Test is a scope. It can contain code that is meant to be executed before each test.

For instance, let’s suppose you have an MUnit Test Suite file with four tests. The code inside an MUnit Before test runs before each of your four tests; it runs four times.

The MUnit Before Test is a top-level scope, thus you can have as many Before tests as you need. They all follow the same execution rule: Run before each test.

If there is more than one Before test, MUnit does not guarantee the order in which the Before tests run amongst themselves.
Before Test example

          
       
1
2
3
<munit:before-test name="before.tests" description="A description">
  <!-- some mule code here --> (1)
</munit:before-test>
1 Define the code you want to run
Attribute Name Description

name

Defines the name of the Before test. The name must be unique inside the test.

description

Describes the actions performed.

One instance in which the MUnit After Suite is useful is when you need to set up a test environment after the whole test runs.

Defining an After Test

The MUnit After Test is a scope. It can contain code that is meant to be executed after each test.

For instance, let’s suppose you have an MUnit Test Suite file with four tests. The code inside an MUnit After Test runs after each of your four tests; it runs four times.

The MUnit After Test is a top level scope, so you can have as many After Tests as you need. They all follow the same execution rule: Run after each test.

If there is more than one After test, MUnit does not guarantee the order in which the After Tests run amongst themselves.
After Test example

          
       
1
2
3
<munit:after-test  name="after.test" description="A description">
  <!-- some mule code here --> (1)
</munit:after-test>
1 Define the code you want to run
Attribute Name Description

name

Defines the name of the After test. The name must be unique inside the test.

description

Describes the actions performed.

One instance in which the MUnit After test is useful is when you need to set up a test environment after the whole test runs.

Defining an MUnit Test

The MUnit Test is the basic building block of an MUnit Test Suite. It represents each test scenario you want to try.

MUnit Test example

         
      
1
2
<munit:test name="my-flow-Test" description="Test to verify scenario 1">
</munit:test>
Table 1. MUnit Test Attributes
Name Description

name

Mandatory. Defines the name of the test. The name must be unique inside the test suite.

description

Mandatory. Describes the scenario being tested.

ignore

Defines if the test should be ignored. If not present, the test is not ignored.

expectException

Defines the exception that should be received after the execution of this test.

Defining Properties

In MUnit, you can load properties from the mule­-app.properties file as well as using the context:property-placeholder to load properties from an additional file.

MUnit provides several ways to override these properties when running MUnit with Anypoint Studio. Properties for the mule-app.properties file are loaded as System properties.

Defining an MUnit Test Description

In MUnit, it’s mandatory that you write a description in your test, that is, the description attribute is mandatory.

Ideally, you should write a useful, representative description of the scenario you are testing. This description displays in the test console before running the test, and also in the reports.

The more representative the description, the more easy to read and troubleshoot any failures.

          
       
1
2
<munit:test name="testingEchoFlow"
    description="We want to test that the flow always returns the same payload as we had before calling it.">

Defining an MUnit Test To Ignore

There may be scenarios where you need to shoot-down a test. Whether this be because the test is failing or because it has nasty side effect. The point is you shouldn’t have to comment out the code.

In some scenarios, you may find it necessary to bypass a defined test, for example if the test fails or produces unwanted side-effects. In this case, MUnit allows you to ignore a specific test so you don’t have to comment out the code.

You can ignore any of your tests by adding the ignore boolean to the test definition, as shown below.

MUnit ignore test example

          
       
1
2
3
4
<munit:test name="my-flow-Test"
      ignore="true"               (1)
      description="Test to verify scenario 1">
</munit:test>
1 Ignore test my-flow-Test
Valid values for ignore are true and false. If the attribute is not present, the default is false.

Defining an Expected Exception

Sometimes, the only thing you want to validate is that the flow or sub-flow you are testing fails and throws a specific exception, which depends on the business logic being tested. In these cases, MUnit provides a simple way to validate the scenario.

You can validate a specific scenario by adding the attribute expectException, as shown below.

MUnit test expect exception example

          
       
1
2
3
<munit:test name="testExceptions" description="Test Exceptions" expectException="">
  <flow-ref name="exceptionFlow"/>
</munit:test>

The attribute expectException expects one of the following:

  • A literal exception class name (canonical form)

  • A MEL expression

MUnit test expected exception class name example

          
       
1
2
3
<munit:test name="testExceptions" description="Test Exceptions" expectException="java.lang.RuntimeException">
  <flow-ref name="exceptionFlow"/>
</munit:test>

If you define that your test expects an exception and none is thrown, the test fails immediately.

expectException - Literal Value

When you provide a literal value, it should take the form of the canonical class name of the exception that is expected. In these cases, Mule always throws a MuleMessagingException. MUnit validates the provided classname if the underlying cause of the MuleMessagingException thrown is of the exact same type.

When providing exceptions in this way, a subclass of the provided exception does not pass the validation — MUnit looks for the exact same type.

expectException - MEL Expression Value

If you choose to use expressions, Mule itself offers a collection of MEL expressions that simplifies the validations of the exceptions thrown.

Name Description

exception.causedBy(exception_type)

Evaluates if the exception was caused by an (instance of) the provided exception type. Example: exception.causedBy(org.mule.example.ExceptionType)

exception.causedExactlyBy(exception_type)

Evaluates if the exception was caused by the specific exception type provided, discarding all other exception types. For example, if the provided exception type is NullPointerException, the expression returns true only if the test returns a NullPointerException. Example: exception.causedExactlyBy(org.mule.example.ExceptionType)

exception.causeMatches(<regex>)

Checks the cause exception type name matches the provided regex. Supports any java regex plus, prefix, suffix. Example: exception.causeMatches(org.mule.example.*)

You can combine any expressions as a boolean expression. For example:
exception.causeMatches('*') && !exception.causedBy(java.lang.ArithmeticException) && !exception.causedBy(org.mule.api.registry.ResolverException)

This MEL expression is meant to be used with the expressions listed above, but no verification is performed done to avoid other usages. The only contract being enforced is: The MEL expression should return a boolean value. If true, the test is successful.

If the MEL expression returns something that cannot be cast to a Boolean value, the test fails.

All MEL expression shortcuts, such as message or payload, are valid. Just bear in mind that if an exception is thrown, the original payload most likely is lost.