DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Architecting a Comprehensive Testing Framework for API and UI Testing
  • Cypress API Testing: A Detailed Guide
  • Maximizing Efficiency With the Test Automation Pyramid: Leveraging API Tests for Optimal Results
  • How to Interpret the Number of Spring ApplicationContexts in Integration Tests

Trending

  • Spring Boot Done Right: Lessons From a 400-Module Codebase
  • Architecting an Embedded Efficiency Layer: A Platform Deep Dive into Day-Two Operational Tuning
  • Slopsquatting: Building a Scanner That Catches AI-Hallucinated Packages Before They Reach Production
  • AI-Driven Integration in Large-Scale Agile Environments
  1. DZone
  2. Testing, Deployment, and Maintenance
  3. Testing, Tools, and Frameworks
  4. Using the OpenAPI Generator To Build Out an Integration Test Client

Using the OpenAPI Generator To Build Out an Integration Test Client

Use your OpenAPI specification file to build your a test client. Use this test client to perform integration tests on your services's API.

By 
Dale Waterworth user avatar
Dale Waterworth
·
Aug. 30, 23 · Tutorial
Likes (1)
Comment
Save
Tweet
Share
7.4K Views

Join the DZone community and get the full member experience.

Join For Free

So, you have written a new API, maybe as much as doing the CRUD endpoints, maybe even some unit tests to boot. 

Now, to gain a little more confidence, integration tests are required to test slices of the new logic. This requires the developer to create a client to access and call the endpoints, as you would in Postman, for instance, and call the new functionality with one's all-encompassing test criteria.

What do I need to do? Well, you need to create a client to call the endpoint, configure it with resource paths, set the HTTP method, set your headers, and create your DTOs, etc., etc., and for every API endpoint, some form of wrapper/function will be required to carry this out.

The OpenAPI Generator does all this for you. You simply give it your OpenAPI spec file, and it generates the client, with all the counterparts and routes set up, for you to simply parameterize and consume.

Getting Started

The project can be checked out from GitHub.

1. Run the Project

./gradlew bootrun

Visiting this link shows the simple CRUD endpoints.

OpenAPI definition


2. Generate the OpenAPI Spec File 

(Note: This can be downloaded but has been automated as part of a Unit Test.)

./gradlew openApiGeneratorTest 

The spec file should now appear in the following:

build/api-docs.json 

3. Generate the Client

./gradlew buildJavaRestTemplateSdk 

The auto-generated client files should now exist in (Note: as the client is NOT compiled, it should go in the resources folder as opposed to the build folder):

src/integrationTest/resources/open-api-client 

That's it! All the build stages are completed — the app is running, OpenAPI Spec has been generated, and the client files have been built.

The Client

A simple CRUD API has been created using the 'Interface Driven Controller' pattern, which nicely hides all the details from the actual implementation. As can be seen below, an interface is used to describe the operations and the annotations OpenAPI uses to generate the test client. 

Observe the Swagger UI to match up the annotations found in the Swagger image above. 

Java
 
@RequestMapping("/users/v1")
@Validated
public interface UserOperations {

    @Operation(summary = "Get a user by id")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "Found the user",
                    content = { @Content(mediaType = "application/json",
                            schema = @Schema(implementation = User.class)) }),
            @ApiResponse(responseCode = "400", description = "Invalid id supplied",
                    content = @Content),
            @ApiResponse(responseCode = "404", description = "User not found",
                    content = @Content) })
    @GetMapping("/{id}")
    @ResponseStatus(HttpStatus.OK)
    User getUser(@PathVariable String id);
}


The OpenAPI uses these annotations to compile the client. The UserController is a simple implementation of this interface and intentionally crudely returns some data for demo purposes.

Test client options.

The Test

The OpenApi client generated a UserControllerApi which takes a simple API client that is configured to match the host and port of the already running service.

Java
 
class UserControllerTest {
    private final static int port = 8080;
    private final static String host = "localhost";
    private static UserControllerApi userController;

    @BeforeAll
    public static void beforeAll() {
        var apiClient = new ApiClient();
        apiClient.setBasePath(String.format("http://%s:%o", host, port));
        userController = new UserControllerApi(apiClient);
    }

    @Test
    public void shouldGetUserList() {
        var users = userController.getUsers();
        assertEquals(1, users.size());
        assertEquals("dale", users.get(0).getName());
    }

  ...
}


Running the tests shows how valid and invalid requests can be made through the API and are caught early on:

./gradlew integrationTest 

Run the tests

The client API structure provides a like-for-like naming convention that matches the names of the functions in the controller, which helps with keeping the context for the next developer to work on.

It also provides a utility function, namely xxxWithHttpInfo() that provides extra fields to test, such as status code, etc.

APIClient

Conclusion 

If you already use OpenAPI/Swagger, then this comes for free with a small amount of effort to implement.

The functionality to automatically build a client that integrates directly with the API and saves valuable developer time in building out boilerplate test code can only be a good thing.

If the API has custom or complex data types, then there can be some issues I have seen with older versions, but the latest seems to have ironed some of those out.

If a team owns many services, then pulling in multiple OpenAPI specs into a single test suite can help prevent unforeseen bugs and errors, backward compatibility, etc.

In the end, the less boilerplate that is required to be written, the better. However, as the complexity and scale grow, the flexibility of the client may not be so fruitful, but for general use cases, it works pretty well and has multiple client implementation options.

Thanks for taking the time to read this, and I hope you enjoyed the article

API UI integration test Testing

Opinions expressed by DZone contributors are their own.

Related

  • Architecting a Comprehensive Testing Framework for API and UI Testing
  • Cypress API Testing: A Detailed Guide
  • Maximizing Efficiency With the Test Automation Pyramid: Leveraging API Tests for Optimal Results
  • How to Interpret the Number of Spring ApplicationContexts in Integration Tests

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook