Testing OpenAPI generated code

I'm working on a client SDK package for my web service, and using the OpenAPI generator for the underlying REST API calls. I'd like to build unit tests for these,* but the mock demonstrated in the WWDC video doesn't really seem appropriate.

What I'd like to do is intercept the generated code’s network request to feed it a canned HTTP response (or at least JSON) that it can then interpret as if it had received it from a real server. Similarly, I want to intercept the request to see that it was formed correctly.

I tried briefly a long time ago to do this by hacking into URLSession, but I didn't get very far.

Any suggestions on how one might accomplish this?

You can accomplish this using URLSession on Apple platforms through URLProtocol, but I'm not sure URLProtocol is fully functional on Linux. Really it depends on what you want to test. Decoding can be tested directly. Testing the calls themselves seems rather antithetical to auto generating your network layer, as it should be generating correct code in the first place.

1 Like

The way to do this is to implement a custom ClientTransport, we use this technique in the tests of the generator itself: swift-openapi-generator/Tests/PetstoreConsumerTests/TestClientTransport.swift at main · apple/swift-openapi-generator · GitHub

And this is what the test allows you to verify: swift-openapi-generator/Tests/PetstoreConsumerTests/Test_Client.swift at cfe078072ebc2fa5ee9fe5f956a1f7afb07d724c · apple/swift-openapi-generator · GitHub

2 Likes

Ah, that looks like exactly what I want, thank you!

1 Like

This is probably the best for the kind of test you need.

The design principle here is that the handler type you define—conforming to the generated APIProtocol—is entirely defined in terms of network-free types. That is to say it's decoupled from the ServerTransport (web framework, in the case of the server) or ClientTransport (HTTP client, in the case of the client).

For servers, this allows you to write unit tests for the business logic in the handlers without using any transport. For this, however, you will need to construct values for the operations Input types. The operation Input and Output types are usually Equatable so using the usual assert-based unit testing is possible.

For clients, this allows you to define a mock server that conform to the protocol which you can use to test the client logic.

However, it sounds like your goal is subtly different.

What I'd like to do is intercept the generated code’s network request to feed it a canned HTTP response (or at least JSON) that it can then interpret as if it had received it from a real server. Similarly, I want to intercept the request to see that it was formed correctly.

In this case, as @Honza_Dvorsky points out, you can implement a custom transport. They typically do the serialization, request, response, deserialization dance, but you can just do whatever you want here, including faking the whole thing.

4 Likes