Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

MuleSoft API Testing With Zerocode Test Framework

DZone's Guide to

MuleSoft API Testing With Zerocode Test Framework

In this post, we'll cover how to use the ZeroCode framework to write REST/SOAP API apps with contract and integration tests using the TDD/BDD approach.

· Integration Zone ·
Free Resource

SnapLogic is the leading self-service enterprise-grade integration platform. Download the 2018 GartnerMagic Quadrant for Enterprise iPaaS or play around on the platform, risk free, for 30 days.

I've been interested in the TDD approach for a while but always struggled to implement it in my projects. After I came across the ZeroCode framework for contract and integration testing, testing REST/SOAP-based applications has become so easy, maintainable, and understandable.

Today, we will cover how we can use the ZeroCode framework to write REST/SOAP API applications with contract and integration tests using the TDD/BDD approach(quick start video).

The details about the ZeroCode Test framework are on Github - ZeroCode

It is a simple Maven-based Java project which uses JSON. Let's get started.

  1. You can clone the sample project from here: PassPort ZeroCode Sample
  2. Open the project in IntelliJ IDEA or in Eclipse. The project structure will look like this: 

Image titleWith this structure, we have divided up our tests with the following folder structure:

 1. Contract Tests

    These tests will hold only the REST API's validating the contract against the API consumers.

Thus, we are validating the JSON body parameters (maxLenght, minLength, regex pattern validation), as well as performing API response validation.

2. Integration Tests

    These tests will perform REST API E2E integration testing. 

In this application, we will integrate with all third-party applications as well as execute applicable business logic and respond with a success/failure JSON response.

We can have separate folder structures for SOAP or Database related tests. Let's dig into how to write test cases.

a) Create a contracttest folder inside the resource folder and create a.json file, for example, successtest.json.

b) Scenario - The scenario names must be unique as it will be easy to identify and it can help to know the scenario name when trying to understand and identify the test case.

c) Steps - You can have multiple steps inside a scenario. Try to keep the steps' names unique so we can reuse step names in order to easily identify which steps passed or failed.

d) Sample - A scenario with multiple steps and how to use the step name in the next steps for assertion or input request:

{
  "scenarioName": "scenario_passport_get_200_success",
  "steps": [
    {
      "name": "create_new_passport",
      "url": "/passports",
      "operation": "POST",
      "request": {
        "body": {
          "userId": 12345,
          "firstName": "John"
        }
      },
      "assertions": {
        "status": 201,
        "body": {
          "id": 999
        }
      }
    },
    {
      "name": "get_passport_details",
      "url": "/passports/${$.create_new_passport.response.body.id}",
      "operation": "GET",
      "request": {
      },
      "assertions": {
        "status": 200,
        "body": {
          "id": 999,
          "userId": 12345,
          "firstName": "John"
        }
      }
    }
  ]
}

e) Once you complete the test scenario's .json file, we will create a JUnit test to run those.

Create a Java class in the contracttest package:

@TargetEnv("github-host.properties")
@RunWith(ZeroCodeUnitRunner.class)
public class EndToEndContractTest {

    @Test
    @JsonTestCase("contract_tests/github_get_user_200_ok.json")
    public void testGitHubGetUser() throws Exception {
    }

    @Test
    @JsonTestCase("contract_tests/github_get_invalid_user_404_not_found.json")
    public void testGitHubGetInvalidUser() throws Exception {
    }

}

In this package: 

1. We have provided properties, file location, where we will define the host and port which will be used to run those test cases.

2. JsonTestCase with a JSON test file location.

ZeroCodeUnitRunner simply picks up the test case from the JSON file and executes it against the host:port given in the properties file.

Test Reports

Use the mvn clean install command to run all the tests. You can view the test results in text format as well as in the interactive report view.

You can view the Test-Reports from the targets/zerocode-interactive.html  and targets/zerocode-csv_<timestamp>.csvfiles. It will give you a searchable view (you see a search box on the top of the page) with status/scenario_name/step_name/status/execution_time and other details. The search is useful on a TEST-STEP-ID basis or SCENARIO basis or PASS/FAIL basis particularly when your tests grow to hundreds in number. 

Test Logs

In case you wish to see logs generated from each test, you can view them from the target/logs folder.

Exclude/Include Test Cases

You can include a test cases package from autobuild(jenkins) by using the Surefire plugin. 

In the pom.xml file, we have introduced a maven-sure-fire plugin in which we have just added contract tests and integration tests to be executed in the Jenkins build

I became a big fan of the ZeroCode Test framework for contract/integration tests for the verification of any MuleSoft/Spring Boot REST API/SOAP endpoint/DB. 

We can use this for any REST API contract and integration test. It is easy to implement, can scale easily, and anyone can easily provide test cases in it without much knowledge of programming. There is a clear separation of concerns of test data from the test framework, which means you can easily share the tests cases among various teams or team members.

Download A Buyer's Guide to Application and Data Integration, your one-stop-shop for research, checklists, and explanations for an application and data integration solution.

Topics:
rest api testing ,tdd testing ,soap api ,mulesoft ,integration

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}