Introduction to Testing Mule
|MuleSoft recommends against deployments to Mule 3.8. Standard Support for this version ended on November 16, 2018, and Mule 3.8 will reach its End of Life on November 16, 2021, when Extended Support ends.|
This page provides a brief overview of testing Mule, linking testing concepts to the tools available to test your Mule applications, as well as to more in-depth pages detailing each concept.
|For Java information, see the Mule Kernel 3.8.1 Test API.|
There are several types of testing. Likely, you focus on one or more types depending on your specific needs, such as specific contexts or products.
From the point of view of a Mule applications developer, it’s fair to say that there are two main types of testing that you should focus on when validating the behavior of your Mule application:
The concept of the unit test may vary according to the programming paradigm that you are working on, but it always revolves around the same core concept: to validate the correctness of an individual unit of source code.
In the context of unit testing, we consider a unit of code to be the smallest testable part of an application. What exactly constitutes the smallest testable part of an application depends on the application. In the case of Mule applications, we consider that the smallest testable part is a Mule flow (
sub-flow); thus this is our unit of code.
Ideally, each test case should be independent from each other.
|It is the work of the developer to ensure test inter-independency.|
The code you test may interact with other units of code or components, and you should take this possibility into account when designing your unit test. A good unit test should ensure the isolation of the unit of code being tested, to avoid mistaking failure in other components for failure in the unit of code being tested.
To isolate your target unit of code, use tools such as the
mock message processor provided by MUnit.
Units of code collaborate between them to create an actual application. You test individual units of code with unit tests, and you test how units of code collaborate between them with integration tests.
The goal of an Integration test is to validate that different units of code and modules work together as intended.
Ideally, integration tests should aggregate units of code modules that have already been successfully unit-tested. For this reason, you should run your integration tests after your unit tests.
Depending on the nature of your application, integration tests may require sandboxes, that is, environments for your application to connect to. When working with sandboxes, take care to ensure that the state of the data in the sandbox is correct for the test to produce the intended result. Perform this before and after running the integration test.
This section defines guidelines for creating flows that are easier to test. Usually, writing testable code implies creating a more configurable, extensible, and readable application.
Modularize your code: Breaking down your code in different files helps with readability. The usual way to do this is to group flows that help to achieve a common goal, or group code according to specific functional criteria.
Modularizing your code allows you to load only that portion of code that you actually wish to test, avoiding the need to load unnecessary configurations during your test.
Write short flows: Long flows are hard to follow and sometimes even harder to code; certainly they are harder to maintain. From the perspective of unit testing, long flows offer too many scenarios that can be triggered by a single point. Long flows can force you to perform very complex evaluations to validate a single scenario and are best avoided.
Define execution environments: Parameterize your code using placeholders. Normal use cases for this include addresses of outbound endpoints, such as DB or HTTP. Using placeholders allows you to modify the actual address when running tests (either unit or integration), and make it easier to promote your code between environments (DEV/QA/UAT/PROD).
Just like you make your code testable, you should code your tests to be readable and maintainable.
One thing that helps is the name you give to the test. Name your test by what to see when the test fails. This rule also applies to the error thrown by the test upon failure. There are few things harder to understand than a wrongly-written or ambiguous error message. As stated earlier, avoid long flows because they are harder to follow. Code your test so that the scenario being covered and the failure conditions are explicit.
MUnit is a Mule testing framework that lets you easily automate testing Mule applications, using both unit and integration tests. MUnit also provides a set of tools, such as a message processor mocking framework that lets you test units of code in actual isolation.
|Mule applications running in Mule Runtime v3.8 and newer can only be tested using MUnit v1.2.0 or higher.|
Mule provides legacy tools for testing your custom Mule applications using Java code. These tools provide the testing functionality but lack some features provided by MUnit, such as mocking.
Mule also offers tools like the Profiler Pack designed to assist in identifying memory leaks in your custom Mule extensions.