diff --git a/modules/ROOT/nav.adoc b/modules/ROOT/nav.adoc index 56492074..fa2da8bc 100644 --- a/modules/ROOT/nav.adoc +++ b/modules/ROOT/nav.adoc @@ -75,8 +75,6 @@ *** xref:sample-data.adoc[Sample Data] *** xref:security-best-practices.adoc[Security] *** xref:threading-asynchronous-processing.adoc[Threading and Asynchronous Processing] - ** xref:testing.adoc[Testing your Module] - *** xref:testing-writing-your-first-test-case.adoc[Writing Your First Test Case] ** xref:about-connector-certification-program-guidelines.adoc[About MuleSoft Connector Certification Program Guidelines] *** xref:certification-guidelines-for-connectors.adoc[Technical Guidelines for Connector Certifications] ** xref:troubleshooting.adoc[Troubleshooting] @@ -84,3 +82,17 @@ ** xref:validators.adoc[Validators with Mule SDK] ** xref:dmt.adoc[DevKit to SDK Migration Tool] * xref:xml-sdk.adoc[XML SDK] +* xref:testing.adoc[Testing Your Module] + ** xref:mtf.adoc[Module Testing Framework (MTF)] + *** xref:testing-writing-your-first-munit-test.adoc[Creating Your Test] + *** xref:mtf-testing-examples.adoc[MTF Test Examples] + **** xref:mtf-testing-sources.adoc[Sources] + **** xref:mtf-expecting-errors.adoc[Expected Errors] + **** xref:mtf-parameterized-tests.adoc[Parameterization] + **** xref:mtf-using-test-classes.adoc[Classes] + **** xref:testing-oauth-modules.adoc[OAuth-Enabled Modules] + **** xref:mtf-metadata-testing.adoc[Metadata] + **** xref:connectivity-testing.adoc[Connectivity] + *** xref:munit-extensions-maven-plugin-configuration.adoc[Configuring the MUnit Extensions Maven Plugin] + *** xref:munit-extensions-maven-plugin.adoc[Operating the MUnit Extensions Maven Plugin] + ** xref:testing-writing-your-first-test-case.adoc[FlowRunner (Deprecated)] diff --git a/modules/ROOT/pages/connectivity-testing.adoc b/modules/ROOT/pages/connectivity-testing.adoc new file mode 100644 index 00000000..a5841d62 --- /dev/null +++ b/modules/ROOT/pages/connectivity-testing.adoc @@ -0,0 +1,71 @@ += Connectivity +ifndef::env-site,env-github[] +include::_attributes.adoc[] +endif::[] + +Test the connectivity defined for your module. + +== Before You Begin + +* Understand how to define a connection for your module. For more information, refer to xref:connections.adoc[]. +* Add the `mtf-tools` dependency to your project: ++ +[source,xml,linenums] +---- + + com.mulesoft.munit + mtf-tools + 1.2.0 + mule-plugin + test + +---- + +== Test Connectivity + +The `test-connectivity` processor establishes a connection using the given configuration. If testing connectivity with the given configuration fails, the processor fails with the proper exception, description, and error type (if present). + +=== Successful Connection + +When you test that a connection is valid, you are validating that the processor does not fail. A successful connection test appears as follows: + +[source,xml,linenums] +---- + + + + + +---- + +=== Invalid Connection + +When a connection fails, the processor fails. Therefore, to test an invalid connection, include an expected exception and expected error description in the test: + +[source,xml,linenums] +---- + + + + + +---- + +If the connection fails with an error type, you can include an expected error type as well: + +[source,xml,linenums] +---- + + + + + +---- + + + diff --git a/modules/ROOT/pages/mtf-expecting-errors.adoc b/modules/ROOT/pages/mtf-expecting-errors.adoc new file mode 100644 index 00000000..beba7438 --- /dev/null +++ b/modules/ROOT/pages/mtf-expecting-errors.adoc @@ -0,0 +1,75 @@ += Expected Errors +ifndef::env-site,env-github[] +include::_attributes.adoc[] +endif::[] + +Validate the error types and error descriptions that your module throws. + +== Before You Begin + +You must know how to define the errors that your module throws. For more information, refer to xref:errors.adoc[]. + +== Example: Error Definition + +In this example, the module defines errors as follows: + +.Error type definition +[source,java,linenums] +---- +public enum SimpleError implements ErrorTypeDefinition { + INVALID_PARAMETER, TIME_OUT, NOT_ALLOWED +} +---- + +.Error type provider +[source,java,linenums] +---- +public class ExecuteErrorsProvider implements ErrorTypeProvider { + @Override + public Set getErrorTypes() { + HashSet errors = new HashSet<>(); + errors.add(SimpleError.INVALID_PARAMETER); + errors.add(SimpleError.TIME_OUT); + return errors; + } +} +---- + +.Operation that throws the error +[source,java,linenums] +---- +@Throws(ExecuteErrorsProvider.class) +public void execute(Integer number) { + if (number <= 0) { + throw new ModuleException("Parameter 'number' should be greater than 0", SimpleError.INVALID_PARAMETER); + } +} +---- + +Use MTF to create tests to validate the expected error type and error description. + +== Validate an Expected Error Type + +To validate that the error thrown by the module in the example has the proper error type: + +[source, xml, linenums] +---- + + + + + +---- + +== Validate an Expected Error Description + +To validate that the error thrown by the module in the example has the proper error description: + +[source, xml, linenums] +---- + + + + + +---- \ No newline at end of file diff --git a/modules/ROOT/pages/mtf-metadata-testing.adoc b/modules/ROOT/pages/mtf-metadata-testing.adoc new file mode 100644 index 00000000..067848c5 --- /dev/null +++ b/modules/ROOT/pages/mtf-metadata-testing.adoc @@ -0,0 +1,361 @@ += Metadata +ifndef::env-site,env-github[] +include::_attributes.adoc[] +endif::[] + +Test the metadata defined for your module. + +== Before You Begin + +* Understand how to define metadata in your module. For more information, refer to xref:metadata.adoc[]. +* Add the `mtf-tools` dependency to your project: ++ +[source,xml,linenums] +---- + + com.mulesoft.munit + mtf-tools + 1.2.0 + mule-plugin + test + +---- + +== Tooling Test + +The `tooling-test` component validates the module's metadata at design time, unlike the `munit:test` component, which validates the module's metadata at execution. The following code describes the `tooling-test` component: + +[source,xml,linenums] +---- + + ... + +---- + +When a suite with a tooling test runs, XML validations are disabled. When testing metadata, it might be necessary to avoid entering required parameters. + +The tooling test can have the following parameters: + +[%header%autowidth.spread,cols="a,a"] +|=== +|Name |Description + +|`name` +| Required. Defines the name of the test. The name must be unique inside the test suite. + +|`description` +|Describes the scenario to test. + +|`ignore` +|Specifies whether to ignore the test. If this parameter is not present, the test is not ignored. + +|`tags` +|Specifies a comma-separated list of tags to assign to the test. + +|`expectFailureCode` +|Defines the failure code that is received after calculating the metadata for this test. + +|`expectFailureMessage` +|Defines the failure message that is received after calculating the metadata for this test. + +|=== + +The tooling test has two main sections: + +* Metadata Scopes ++ +Wraps the component in which to calculate metadata and defines the metadata information to obtain. Possible values are: ++ +** Metadata keys +** Input metadata +** Output metadata +** Attributes metadata + +* Validation ++ +Contains all the validations regarding the result of the metadata scope. + +== Metadata Scopes + +Use metadata scopes in the tooling test. You can use only one metadata scope in each test and you can use either an operation or a source in each metadata scope. + +=== Metadata Keys + +The `metadata keys` scope obtains the metadata keys for the module. The `payload` contains a map, in which the key is the metadata key ID and the value is the metadata key: + +[source,xml,linenums] +---- + + + + + + + + +---- + +=== Input Metadata + +The `input metadata` scope obtains the metadata type for the specified parameter of the module. The `payload` contains a JSON representation of the metadata type: + +[source,xml,linenums] +---- + + + + + + + + +---- + +=== Output Metadata + +The `output metadata` scope obtains the metadata type for the output `payload` of the module, which contains a JSON representation of the metadata type: + +[source,xml,linenums] +---- + + + + + + + + + + + + +---- + +=== Attributes Metadata + +The `attributes metadata` scope obtains the metadata type for the `attributes` metadata of the module. The `payload` contains a JSON representation of the metadata type: + +[source,xml,linenums] +---- + + + + + + + + + + +---- + +The `mtf:get-values` element retrieves the possible values for the specified parameter of the module. The `payload` contains a JSON representation of the values. + +[source,xml,linenums] +---- + + + + + + + + + + +---- + +== Validation + +A common use case when testing metadata is validating failures that might occur during metadata calculation. To validate these failures, use the `expectFailureCode` and `expectFailureMessage` parameters: + +[source,xml,linenums] +---- + + + + + +---- + +=== Assert Type Processor + +Use the assert type processor to assert the metadata type structure returned by metadata scopes such as `get-input-metadata`, `get-output-metadata`, and `get-attributes-metadata`. + +The assert type processor compares the structure of both metadata types and ignores fields such as `format` or `annotations`. To perform assertions over these fields, use the `payload` result of the metadata scopes operations as shown in the previous examples. + +If the assertion fails, the processor throws a `java.lang.AssertionError` error. + +==== From Class + +To compare a metadata type structure with another metadata type structure obtained from a Java class, use the `fromClass` parameter: + +[source,xml,linenums] +---- + + + + + + + + +---- + +The `actual` field defaults to `payload`. You can choose to not specify the `actual` field. For example: + +[source,xml,linenums] +-- + +-- + +==== From Schema + +To compare a metadata type structure with another metadata type structure obtained from a schema, use the `fromSchema` parameter. + +The `fromSchema` parameter supports metadata types, such as JSON schema, XSD schema, and RAML data types. The file extensions must be `.json`, `.xsd`, and `.raml` respectively, and must be stored in the `src/test/resources` folder. + +[source,xml,linenums] +---- + + + + + + + + +---- + +The `actual` field defaults to `payload`. You can choose to not specify the `actual` field. For example: + +[source,xml,linenums] +-- + +-- + +== Example: Metadata Test + +Implementations provided in the following example use fixed values to simplify the code. You must obtain metadata through external services. + +This module defines the following metadata: + +.Operation with metadata +[source, java, linenums] +---- +@OutputResolver(output = ExampleOutputResolver.class) +public Object withMetadata(@MetadataKeyId(ExampleKeysResolver.class) String param) { + return null; +} +---- + +.TypeKeysResolver +[source, java, linenums] +---- +public class ExampleKeysResolver implements TypeKeysResolver { + + @Override + public Set getKeys(MetadataContext metadataContext) { + Set metadataKeys = new HashSet<>(); + metadataKeys.add(newKey("firstKey").withDisplayName("First Key").build()); + metadataKeys.add(newKey("secondKey").withDisplayName("Second Key").build()); + return metadataKeys; + } + + @Override + public String getCategoryName() { + return "ExampleCategory"; + } + +} +---- + +.OutputResolver +[source, java, linenums] +---- +public class ExampleOutputResolver implements OutputTypeResolver { + + @Override + public String getResolverName() { + return "exampleResolver"; + } + + @Override + public MetadataType getOutputType(MetadataContext context, String param) throws MetadataResolvingException { + if (param == null || param.isEmpty()) { + throw new MetadataResolvingException("No metadata available for an empty param", FailureCode.INVALID_METADATA_KEY); + } + ObjectTypeBuilder objectType = context.getTypeBuilder().objectType(); + objectType.addField().key("name").value().stringType(); + objectType.addField().key("age").value().numberType(); + return objectType.build(); + } + + @Override + public String getCategoryName() { + return "ExampleCategory"; + } +} +---- + +== Test Metadata Keys + +The following example validates that the keys have the proper `Display` names: + +[source, xml, linenums] +---- + + + + + + + + + +---- + +== Test a Metadata Type + +The following test validates the `Metadata Type` output value returned by the operation: + +[source, xml, linenums] +---- + + + + + + + + + + + + +---- + +== Test an Expected Failure + +In the previous example, the module throws a `MetadataResolvingException` error when the parameter is null or empty. + +The following test validates that the proper failure code and message are thrown when the parameter is invalid: + +[source, xml, linenums] +---- + + + + + +---- + + + + + + diff --git a/modules/ROOT/pages/mtf-parameterized-tests.adoc b/modules/ROOT/pages/mtf-parameterized-tests.adoc new file mode 100644 index 00000000..0ed81ef8 --- /dev/null +++ b/modules/ROOT/pages/mtf-parameterized-tests.adoc @@ -0,0 +1,101 @@ += Parameterization +ifndef::env-site,env-github[] +include::_attributes.adoc[] +endif::[] + +Use a parameterized suite to run the same tests with different inputs. For more information, refer to xref:munit::parameterized.adoc[]. + +== Example: Configuration Parameterization + +The following example shows a test suite with two parameterizations, each pointing to a different configuration: + +[source, java, linenums] +---- +public Integer withConfig(@Config ExampleConfig config) { + return config.getValue(); +} +---- + +Use the following code to test different configurations: + +[source, xml, linenums] +---- + + + + + + + + + + + + + + + + + + + + + + + + + + + + +---- + +== Example: Input Data Parameterization + +Suppose you want to execute one operation but with different inputs, and each input has different expected outputs. For example, testing an operation that replaces one string input with another. Use the following syntax for your operation: + +[source, java, linenums] +---- +public String replace(String input, String toReplace, String replacement) { + return input.replace(toReplace, replacement); +} +---- + +Use the following code to test for several different inputs for one operation: + +[source, xml, linenums] +---- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +---- + + + + diff --git a/modules/ROOT/pages/mtf-testing-examples.adoc b/modules/ROOT/pages/mtf-testing-examples.adoc new file mode 100644 index 00000000..d62bdf29 --- /dev/null +++ b/modules/ROOT/pages/mtf-testing-examples.adoc @@ -0,0 +1,18 @@ += MTF Test Examples +ifndef::env-site,env-github[] +include::_attributes.adoc[] +endif::[] + +Here are some examples of tests that demonstrate common uses, patterns, and best practices for your modules. + +[%header%autowidth.spread,cols="a,a"] +|=== +| Example | Description +| xref:mtf-testing-sources.adoc[Sources] | Learn how different types of sources require different types of testing approaches. +| xref:mtf-expecting-errors.adoc[Expected Errors] | Validate that your module throws the proper errors. +| xref:mtf-parameterized-tests.adoc[Parameterization] | Use parameterization to reuse your tests. +| xref:mtf-using-test-classes.adoc[Classes] | Use auxiliary classes for your tests. +| xref:testing-oauth-modules.adoc[OAuth-Enabled Modules] | Test modules that use OAuth authentication. +| xref:mtf-metadata-testing.adoc[Metadata] | Test your module's metadata. +| xref:connectivity-testing.adoc[Connectivity] | Test your module's connectivity. +|=== \ No newline at end of file diff --git a/modules/ROOT/pages/mtf-testing-sources.adoc b/modules/ROOT/pages/mtf-testing-sources.adoc new file mode 100644 index 00000000..fa40ebd1 --- /dev/null +++ b/modules/ROOT/pages/mtf-testing-sources.adoc @@ -0,0 +1,115 @@ += Sources +ifndef::env-site,env-github[] +include::_attributes.adoc[] +endif::[] + +Because you must place sources at the beginning of a flow, they cannot appear directly in the test. To test a source, you must have a flow with the source you want to test, and then a test that triggers the source. + +There are several types of sources, each with its own distinct testing strategy. + +== Sources That Emit a Response + +The most common type of test is when the source generates a synchronous response. To test a source that emits a response, trigger the source to get that response, and then assert it. + +For example, in the case of `http:listener`, you can trigger the source with `http:request`: + +[source, xml, linenums] +---- + + + + + + + + + + + + <...> + + + + + +---- + +== Polling Sources + +Because a polling source polls items periodically with a given scheduling strategy, the test must trigger the polling source and wait for the next poll. Then, the test can validate the response generated by the polling source. + +=== Trigger a Polling Source a Single Time + +You can trigger the polling source a single time. For example, for a `file:listener` operation, you can trigger the polling source by creating new files: + +[source, xml, linenums] +---- + + + + + + + + #[payload] + + + + + + + + + + <...> + + + + + + + +---- + +=== Trigger a Polling Source Multiple Times + +You can trigger the polling source multiple times: + +[source, xml, linenums] +---- + + + + + + + + #[payload] + + + + + + + + + + <...> + + + + + + + + + + + + + +---- + +== See Also + +* xref:sources.adoc[] \ No newline at end of file diff --git a/modules/ROOT/pages/mtf-using-test-classes.adoc b/modules/ROOT/pages/mtf-using-test-classes.adoc new file mode 100644 index 00000000..916eeb72 --- /dev/null +++ b/modules/ROOT/pages/mtf-using-test-classes.adoc @@ -0,0 +1,72 @@ += Classes +ifndef::env-site,env-github[] +include::_attributes.adoc[] +endif::[] + +When creating test cases, use Java classes located in `src/test/java` with DataWeave or Java Module. + +In the following example, assume that your class is located in `src/test/java/com/example/MyUtilClass.java`: + +[source, java, linenums] +---- +package com.example.test; + +public class Helper { + + public static long getCurrentMillis() { + return System.currentTimeMillis(); + } +} +---- + +== Use Classes with DataWeave + +To invoke static methods using DataWeave, add the `java!` prefix to the package name of the class: + +[source, xml, linenums] +---- + + + + + + + + +---- + +== Use Classes with Java Module + +To use classes with Java Module: + +. Ensure that Java Module is in your project: ++ +[source, xml, linenums] +---- + + org.mule.module + mule-java-module + ${javaModule.version} + mule-plugin + test + +---- +. Use any of the operations in Java Module. In this example, invoke a static method of a class: ++ +[source, xml, linenums] +---- + + + + + + + + +---- + +The MUnit Extensions Maven Plugin automatically exports any test packages and test resources in your project. If your module already exports a class located in `src/main/java`, then any test classes with the same package located in `src/test/java` are not exported because this causes a conflict. To export both classes, change the test classes to a different package. + + + + diff --git a/modules/ROOT/pages/mtf.adoc b/modules/ROOT/pages/mtf.adoc new file mode 100644 index 00000000..8c858e08 --- /dev/null +++ b/modules/ROOT/pages/mtf.adoc @@ -0,0 +1,20 @@ += Module Testing Framework (MTF) +ifndef::env-site,env-github[] +include::_attributes.adoc[] +endif::[] + +Use Module Testing Framework (MTF) to create tests for modules built with Mule SDK for Java or XML to ensure the interaction between modules and Mule runtime is compatible with the Mule ecosystem. MTF supports functional tests for your modules. You run these tests during the `integration-test` phase of your module's lifecycle. + +MTF is a plugin that extends MUnit. While MUnit tests applications, MTF leverages MUnit to specifically test modules. If you build custom modules, you must use MTF to create tests to ensure module functionality and compatibility. + +== Before You Begin + +Before you begin using MTF, you must have: + +* Familiarity with MUnit +* Anypoint Studio + +== See Also + +* xref:munit::index.adoc[MUnit] +* xref:studio::index.adoc[Anypoint Studio] diff --git a/modules/ROOT/pages/munit-extensions-maven-plugin-configuration.adoc b/modules/ROOT/pages/munit-extensions-maven-plugin-configuration.adoc new file mode 100644 index 00000000..67661fba --- /dev/null +++ b/modules/ROOT/pages/munit-extensions-maven-plugin-configuration.adoc @@ -0,0 +1,521 @@ += Configuring the MUnit Extensions Maven Plugin +ifndef::env-site,env-github[] +include::_attributes.adoc[] +endif::[] + +The MUnit Extensions Maven plugin provides testing capabilities for extension development. Learn how to configure the MUnit Extensions Maven plugin to test your modules. + +== Specify Additional Argument Lines + +Because you run the tests in a new JVM, you can specify additional argument lines to the JVM. Specify each argument in a separate `argLine`. + +[source,xml,linenums] +---- + + + com.mulesoft.munit + munit-extensions-maven-plugin + + ... + + -XX:MaxPermSize=512m + -Xmx1024m + + ... + + + +---- + +== Enable Runtime Discovery + +Runtime discovery looks for all Mule runtime versions published on Nexus to run +against your tests. + +To enable runtime discovery, add the following configuration to the MUnit Extensions Maven plugin: + +[source,xml,linenums] +---- + + + com.mulesoft.munit.tools + munit-extensions-maven-plugin + + ... + + + `Product` //<1> + + + ... + + + +---- + +The `Product` can be CE (Community Edition), EE (Enterprise Edition), or ALL (both CE and EE). For example, if the `Product` is CE, the runtime discovery feature is enabled for all released CE runtimes. + +From the command line, use the `discoverRuntimes.product` property to enable runtime discovery. + +=== Include Snapshots + +To include snapshot versions of Mule runtime, add an `includeSnapshots` property to the runtime configuration: + +[source,xml,linenums] +---- + + + CE + true + + +---- + +From the command line, use the `discoverRuntimes.includeSnapshots` property to include snapshots. The default value is `false`. + +=== Discover Only the Latest Patches + +To discover only the latest patch versions of Mule runtime, add a `latestPatches` property to the runtime configuration: + +[source,xml,linenums] +---- + + + CE + true + + +---- + +From the command line, use the `discoverRuntimes.latestPatches` property to discover only the latest patches. The default value is `true`. + +=== Discover Since a Minimum Version + +By default, runtime discovery searches for all Mule runtime versions since the `minMuleVersion` of the module. To change the minimum version, add a `minMuleVersion` property to the runtime configuration: + +[source,xml,linenums] +---- + + + CE + 4.1.2 + + +---- + +From the command line, use the `discoverRuntimes.minMuleVersion` property to discover runtimes since a minimum version. The default value is the `minMuleVersion` of the module. + +=== Run Against Additional Runtimes + +By default, the MUnit Extensions Maven plugin runs against the `minMuleVersion` and the required product of the module. To specify additional runtimes to run against, add `additionalRuntime` properties to the runtime configuration: + +[source,xml,linenums] +---- + + + MULE_EE:4.1.2 + MULE:4.1.1 + + +---- + +From the command line, use the `additionalRuntimes` property to run against additional runtimes. + +=== Skip Runtime Discovery + +To skip runtime discovery, add a `skip` property to the runtime configuration: + +[source,xml,linenums] +---- + + + CE + true + + +---- + +From the command line, use the `discoverRuntimes.skip` property to skip runtime discovery. The default value is `false`. + +== Use Dynamic Ports + +[IMPORTANT] +MUnit 2.2 and later introduces the `dynamic-port` global element, which you can use to define dynamic ports at the MUnit suite level. + +Use this element instead of the plugin configuration described below to set the dynamic port from both Maven and Studio. + +For more information about how to configure this element, refer to xref:munit::dynamic-ports.adoc[Dynamic Ports]. + +When testing a module in a continuous integration (CI) environment, you might encounter the following scenario: + +`Your test tries to open a specific port. The port is already in use. The test fails with a port binding exception.` + +To solve this, use the dynamic ports built-in feature in the MUnit Extensions Maven plugin to have your test use a free port. Dynamic ports instruct the MUnit Extensions Maven plugin to look for unbound ports and reserves them before running the tests over the module. Each selected port is placed in a system property under the name indicated in the configuration. The test can acquire the port number through the use of placeholders afterward. + +The ports that the MUnit Extensions Maven plugin can select are in the following range: `[40000,50000)`. + +The dynamic ports feature is available only as part of the MUnit Extensions Maven plugin. This feature doesn't work when running tests from inside Anypoint Studio. + +=== Enable Dynamic Ports + +To enable the dynamic ports feature, add the following code to the `configuration` section of the MUnit Extensions Maven plugin: + +[source,xml,linenums] +---- + + + com.mulesoft.munit.tools + munit-extensions-maven-plugin + + ... + + a.dynamic.port + + ... + + + +---- + +If you have the `${http.port}` placeholder in your test, the configuration looks like this: + +[source,xml,linenums] +---- + + http.port + +---- + +== Disable Surefire Reports + +MUnit has built-in support for Surefire. You can disable this support if it's not needed. + +[source,xml,linenums] +---- +false +---- + +The reports are located under `${project.build.directory}/surefire-reports`. + +The default value is `true`. + +== Run Specific Tests + +To run a specific test, add an `munitTest` property for each specific test to the configuration section of the MUnit Extensions Maven plugin: + +[source,xml,linenums] +---- + + + com.mulesoft.munit.tools + munit-extensions-maven-plugin + + ... + example-MunitTest-suite.xml + ... + + + +---- + +== Run Tests with Specific Tags + +To run tests with specific tags, add an `munitTags` property for the tests with the specific tags to the configuration section of the MUnit Extensions Maven plugin. Separate the tags with commas, for example: + +[source,xml,linenums] +---- + + + com.mulesoft.munit.tools + munit-extensions-maven-plugin + + ... + exampleMUnitTag,exampleMUnitTag2 + ... + + + +---- + +== Skip MUnit Tests + +To skip MUnit tests, add a `skipMunitTests` property to skip MUnit tests to the configuration section of the MUnit Extensions Maven plugin: + +[source,xml,linenums] +---- + + + com.mulesoft.munit.tools + munit-extensions-maven-plugin + + ... + True + ... + + + +---- + +== Skip Tests After One Suite Fails + +To skip the rest of the tests if one test suite fails, add a `skipAfterFailure` property to the configuration section of the MUnit Extensions Maven plugin: + +[source,xml,linenums] +---- + + + com.mulesoft.munit.tools + munit-extensions-maven-plugin + + ... + true + ... + + + +---- + +The default value is `false`. + +== Specify the Mule Runtime Version + +To specify the Mule runtime version that your tested module runs on, add a `runtimeVersion` property for the Mule runtime version to the configuration section of the MUnit Extensions Maven plugin: + +[source,xml,linenums] +---- + + + com.mulesoft.munit.tools + munit-extensions-maven-plugin + + ... + 1.2.3 + ... + + + +---- + +If this option is set, runtime discovery and `additionalRuntimes` don't take effect. + +== Specify the Runtime Product + +You can specify the type of runtime that your tested module runs on. + +Values are `MULE` for Community Edition, and `MULE_EE` for Enterprise Edition. + +[source,xml,linenums] +---- + + + com.mulesoft.munit.tools + munit-extensions-maven-plugin + + ... + MULE + ... + + + +---- + +If this option is set, runtime discovery and `additionalRuntimes` don't take effect. + +== Specify the JVM + +To specify the JVM (Java executable) that your tested module runs on, populate the `jvm` property with the path to the executable: + +[source,xml,linenums] +---- + + + com.mulesoft.munit.tools + munit-extensions-maven-plugin + + ... + /path/to/jdk/bin/java + ... + + + +---- + +From the command line, use the `-Dmunit.jvm` property to specify the JVM. + +== Set Environment Variables + +To set additional environment variables during the test run, specify them with the respective key and value: + +[source,xml,linenums] +---- + + + com.mulesoft.munit.tools + munit-extensions-maven-plugin + + ... + + exampleValue + val2 + + ... + + + +---- + +Use environment variables to replace `${MY_ENV}` and `${MY_OTHER_ENV}`. + +== Redirect Test Output to a File + +When running several tests, the build output can be complicated to read. You can redirect the build output of each test suite to a file so that the build output contains the test results and the respective file contains the standard output of each test suite. + +These files are located in the `testOutputDirectory` folder and follow the `munit.${suiteName}-output.txt` naming convention, in which `suiteName` is the name of the XML file relative to the MUnit test folder. + +To keep the build output clean, the test run output that doesn't belong to a particular suite doesn't print, but you can enable it by running Maven in debug mode. + +[source,xml,linenums] +---- + + + com.mulesoft.munit.tools + munit-extensions-maven-plugin + + ... + true + ... + + + +---- + +The default value is `false`. + +== Define System Properties Variables + +You can define specific system variables needed for your MUnit test to run successfully: + +[source,xml,linenums] +---- + + + com.mulesoft.munit.tools + munit-extensions-maven-plugin + + ... + + my.property.value + + ... + + + +---- + +Depending on the execution context, the system properties values might vary. When referencing these properties, override their value to enforce test reproducibility. + +You can do so by using the ­`-D` argument when running MUnit with Maven. + +Variables passed with the `-D` argument take full priority over any other property, for example, `-Dmy.property.key=my.property.another.value`. + +== Test Output Directory + +You can choose the location where the test output files are created. +The specified path can be an absolute path or a Maven placeholder. + +If the specified path is an absolute path, the test output directory looks like this: + +[source,xml,linenums] +---- + + + com.mulesoft.munit.tools + munit-extensions-maven-plugin + + ... + /my/absolute/path + ... + + + +---- + +If the specified path is a Maven placeholder, the test output directory looks like this: + +[source,xml,linenums] +---- +${project.build.directory}/my/output/folder +---- + +By default, the files are created in `${project.build.directory}/munit-reports/output/`. + +== Specify Shared Libraries + +When requiring external libraries (as explained in xref:external-libs.adoc[]), specify +these libraries as `sharedLibraries`. You must also have the corresponding dependencies in the project. + +For example, if you define the following external library in your module: + +[source,java,linenums] +---- +@ExternalLib(name = "My External Library", +requiredClassName = "com.example.MyClass", +coordinates = "com.example:my-external-library:1.2.3") +---- + +You must configure the plugin in the following way: + +[source,xml,linenums] +---- + + + com.mulesoft.munit.tools + munit-extensions-maven-plugin + + ... + + + com.example + my-external-library + + + ... + + + +---- + +== Import External Suites and Resources + +To reuse suite files that are present in an external artifact across different modules, include the suite files in the configuration as if they are present in the `src/test/munit` and `src/test/resources` folders. Ensure that you add the dependencies in the plugin's classpath. + +[source,xml,linenums] +---- + + + com.mulesoft.munit.tools + munit-extensions-maven-plugin + + ... + + suite1.xml + suite2.xml + + + example.json + + ... + + + + com.example + my-dependency + 1.0.0 + + + + +---- + +If any of the suite files or resources aren't present in the classpath, the plugin fails. + +== See Also + +* xref:munit-extensions-maven-plugin.adoc[] diff --git a/modules/ROOT/pages/munit-extensions-maven-plugin.adoc b/modules/ROOT/pages/munit-extensions-maven-plugin.adoc new file mode 100644 index 00000000..d54e0086 --- /dev/null +++ b/modules/ROOT/pages/munit-extensions-maven-plugin.adoc @@ -0,0 +1,96 @@ += Operating the MUnit Extensions Maven Plugin +ifndef::env-site,env-github[] +include::_attributes.adoc[] +endif::[] + +Learn how to run your tests by using the MUnit Extensions Maven plugin. + +== Run MUnit Tests for a Module Project + +To run MUnit tests for your module: + +[source,console] +---- +mvn clean verify +---- + +== Run a Specific MUnit Test Suite + +You can instruct the MUnit Extensions Maven plugin to run tests that belong only to a specific test suite by using the `munit.test` property: + +[source,console] +---- +mvn clean verify -Dmunit.test= +---- + +The `munit.test` property accepts regular Java expressions applied to the name of the MUnit test suite file. The path is relative to `src/test/munit`. + +For example: + +[source,console] +---- +mvn clean verify -Dmunit.test=.*my-test.* +---- + +You can leverage this feature by adding naming conventions to your MUnit test suites. + +== Run Specific MUnit Tests + +In the same way that you instruct MUnit to run one test suite, you can also instruct MUnit to run a specific test inside that test suite. To do so, use the `munit.test` property, followed by `#` and the test name: + +[source,console] +---- +mvn clean verify -Dmunit.test=# +---- + +The test also accepts regular expressions applied to the `name` attribute: + +For example: + +[source,console] +---- +mvn clean verify -Dmunit.test=.*my-test.*#.*test-scenario-1.* +---- + +The MUnit Extensions Maven plugin flags tests inside the MUnit test suite as *ignored* if they don't match the regular expression. + +== Run Tests Using a Specific Tag + +You can choose to run only the tests that you grouped under one specific tag: + +[source,console] +---- +mvn clean verify -Dmunit.tags= +---- + +For more information about how to tag your tests, refer to xref:munit::munit-test-concept.adoc#test-tag-attribute[Test Tag Attribute]. + +== Skip All Tests + +When building your module, you can prevent a test from running by using the `skipTests` parameter: + +[source,console] +---- +mvn clean verify -DskipTests +---- + +== Debug Tests + +When testing your module, you can debug your code. MUnit leverages Java remote debugging, so use the `munit.debug` parameter to debug your tests: + +[source,console] +---- +mvn clean verify -Dmunit.debug +---- + +The default debugger listens on port 5005. You can override the debugger JVM argument line by specifying it as the value of the property: + +[source,console] +---- +mvn clean verify -Dmunit.debug="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8002" +---- + +== See Also + +* xref:munit::munit-showing-results.adoc[] +* xref:munit-extensions-maven-plugin-configuration.adoc[] diff --git a/modules/ROOT/pages/testing-oauth-modules.adoc b/modules/ROOT/pages/testing-oauth-modules.adoc new file mode 100644 index 00000000..bb140751 --- /dev/null +++ b/modules/ROOT/pages/testing-oauth-modules.adoc @@ -0,0 +1,78 @@ += OAuth-Enabled Modules +ifndef::env-site,env-github[] +include::_attributes.adoc[] +endif::[] + +Mule runtime engine supports authorization through various OAuth grant types, including the Authorization Code grant type, which allows an external system (for example, your Mule application) to operate on behalf of a user without requiring user authentication. + +However, because the Authorization Code grant type forces human intervention in the authentication process that identifies users using OAuth (OAuth dance), building an automated test for an application using this grant type is challenging. + +To overcome this challenge, use the Storage Event processor to bypass the OAuth dance by manually providing a valid access token. Ensure the following requirements are met: + +* You must manually obtain the token. +* You must be aware that the token eventually expires. ++ +How often the token expires depends on the service provider you are connecting to. +* You must obtain a new token and update the test with it. + +== Example: OAuth-Enabled Module + +Consider the following configuration of Salesforce Connector using OAuth authentication: + +[source,xml,linenums] +---- + + + //<1> + + + + + + //<2> + + +---- +[calloutlist] +.. The application defines an object store named `tokenStore`. +.. The application uses the `tokenStore` object store to store the OAuth token. + +To use the OAuth token stored in `tokenStore` in an MUnit test, create a flow and insert your token in an MUnit Storage Event processor: + +[source,xml,linenums] +---- + + + #[{param1: 'foo', param2: 3}] + + +---- + +Note that the `ownerConfigName` element matches the name of the Salesforce configuration. The access token and other properties shown here are placeholders for the values that you obtain by manually performing the OAuth dance. You can then supply the token to the MUnit test through system properties, a properties file, or any other mechanism you choose. + +After you supply the token values, your MUnit test has the following structure: + +[source,xml,linenums] +---- + + + //<1> + + + //<2> + + + .... Your assertions here .... + + +---- +[calloutlist] +.. Inserting the token by invoking the `storeOAuthToken` flow is the very first step in the test. +.. The `` operation references the same config name and `resourceOwnerId` that matches the token you inserted. diff --git a/modules/ROOT/pages/testing-writing-your-first-munit-test.adoc b/modules/ROOT/pages/testing-writing-your-first-munit-test.adoc new file mode 100644 index 00000000..ba4e2a43 --- /dev/null +++ b/modules/ROOT/pages/testing-writing-your-first-munit-test.adoc @@ -0,0 +1,204 @@ += Creating Your Test +ifndef::env-site,env-github[] +include::_attributes.adoc[] +endif::[] + +To test your module, you must create MUnit tests because MTF depends on MUnit. To test your module, you must: + +. <>. +. <>. +. <>. + +The following example, based on the module project generated with the Mule Extensions Archetype in xref:getting-started.adoc#generating-a-project-using-the-maven-archetype-directly[Creating Your First SDK Project], shows a step-by-step process of testing a module using MUnit. + +[[configure-your-module]] +== Configure Your Module + +To configure your module to run your MUnit tests, you must configure your `pom.xml` file: + +. Add the following properties: ++ +[source,xml,linenums] +---- + + … + + + src/test/munit + ${basedir}/target/test-mule/munit + 1.2.0 + 3.1.0 + 3.1.0 + ... + + ... + +---- ++ +NOTE: Starting from version 1.x, this configuration might already be set up given a minMuleVersion parent. ++ +. Add the Maven Resources Plugin: ++ +[source,xml,linenums] +---- + + … + + + ... + + maven-resources-plugin + ${mavenResourcesVersion} + + + copy-munit-resources + process-test-resources + + copy-resources + + + ${munit.output.directory} + + + ${munit.input.directory} + true + + + + + + + ... + + + ... + +---- +. Add the MUnit Extensions Maven plugin: ++ +[source,xml,linenums] +---- + + … + + + ... + + com.mulesoft.munit + munit-extensions-maven-plugin + ${munit.extensions.maven.plugin.version} + + + + test + + integration-test + + + + + com.mulesoft.munit + munit-runner + ${munit.version} + mule-plugin + + + com.mulesoft.munit + munit-tools + ${munit.version} + mule-plugin + + + + ... + + + ... + +---- + +[[write-your-test]] +== Write Your MUnit Test + +To test your module, your MUnit test must execute the module's operations and make assertions about the result of these executions. + +You must place the MUnit test XML inside the `src/test/munit` folder of the module project. + +[source,xml,linenums] +---- + + + + + + + + + + + + + + + + + + + + + + + + + + + +---- + +[[run-your-test]] +== Run Your MUnit Test + +Run your test from the command line using Maven: + +[source,bash,linenums] +---- +mvn clean verify +---- + +This outputs the result of your test run: + +[source,bash,linenums] +---- +================================================================================ +=== Running suite: basic-operations-test.xml === +================================================================================ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++ Running test: sayHiTest + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++ Running test: retrieveInfoTest + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +================================================================================ += Tests run: 2 - Failed: 0 - Errors: 0 - Skipped: 0 - Time elapsed: 2.55 sec = +================================================================================ +---- + +== See Also + +* xref:munit-extensions-maven-plugin-configuration.adoc[] +* xref:munit-extensions-maven-plugin.adoc[] + diff --git a/modules/ROOT/pages/testing-writing-your-first-test-case.adoc b/modules/ROOT/pages/testing-writing-your-first-test-case.adoc index 07973cd0..c7a63af4 100644 --- a/modules/ROOT/pages/testing-writing-your-first-test-case.adoc +++ b/modules/ROOT/pages/testing-writing-your-first-test-case.adoc @@ -3,6 +3,8 @@ ifndef::env-site,env-github[] include::_attributes.adoc[] endif::[] +NOTE: This guide uses FlowRunner, which is deprecated. To test your modules, refer to the xref:mtf.adoc[MTF] documentation instead. + This section provides a step-by-step introduction to testing a module's operation. It explains the basics of test cases that you must perform. @@ -47,7 +49,7 @@ The Mule app XML must be placed inside the `src/test/resources` folder of the mo - + @@ -120,7 +122,7 @@ of the flow execution. This variable is required for obtaining the value of the Object payloadValue = event.getMessage() .getPayload() .getValue(); - assertThat(payloadValue, is("Hello Mariano Gonzales!!!")) + assertThat(payloadValue, is("Hello!")) ---- === 4.3 Summary @@ -136,7 +138,7 @@ public void executeSayHiOperation() throws Exception { .getMessage() .getPayload() .getValue()); //<2> - assertThat(payloadValue, is("Hello Mariano Gonzales!!!")); //<3> + assertThat(payloadValue, is("Hello!")); //<3> } ---- <1> Executes the `sayHiFlow` flow. diff --git a/modules/ROOT/pages/testing.adoc b/modules/ROOT/pages/testing.adoc index f33c58d4..c4556b81 100644 --- a/modules/ROOT/pages/testing.adoc +++ b/modules/ROOT/pages/testing.adoc @@ -3,9 +3,10 @@ ifndef::env-site,env-github[] include::_attributes.adoc[] endif::[] -Testing ensures that a piece of code works correctly. Testing a module is more than simply creating test cases for the business logic. A lot of testing of the interaction -between the Module and Mule is required to ensure compatibility with the Mule ecosystem. +Test your module built with Mule SDK for Java or XML to ensure the interaction between your module and Mule runtime is compatible with the Mule ecosystem. -Here are a series of articles that explain in detail how to test your module. It provides a step-by-step introduction on how to test a module. It explains the basis of a Module Test Case and how to execute a simple operation from a Module. +You can test your module with Module Testing Framework (MTF). FlowRunner is deprecated. + +* xref:mtf.adoc[Module Testing Framework (MTF)] +* xref:testing-writing-your-first-test-case[FlowRunner (Deprecated)] -* <> (with xref:testing-writing-your-first-test-case.adoc#testing-flowrunner[FlowRunner])