Greetings, today I will try to give you information about the logic of mocking and using Wiremock.
Mock objects are simulated objects that emulate the behavior of natural objects in a controlled manner. To test the behavior of an object, we need to mock the dependencies of that object. In addition, while testing an API, we can mock the components it depends on, and prevent faulty situations in other APIs from destabilizing our API.
First of all, I will write a simple API that requests an API, and then I will talk about how to mock this request with wiremock. I chose The Star Wars API as the API that I’m requesting. You can learn about its use at https://swapi.dev/documentation.
You can review the 2 projects I used in my article below.
I wrote our API in java and used spring boot. The API has a single endpoint and the orderRequest requested from the user on my endpoint that performs this post /createOrder operation is as follows.
I call swapi with taking the value in the peopleId field here. For example, when entered 1 to peopleId, it goes to https://swapi.dev/api/people/1 and returns the following response.
Then, as a response, I will return the PeopleResponse object that the swap above returns and the entered peopleId, orderName, and orderDescription values. I didn’t need to use DB as this is a very simple API. Below is an example of orderResponse.
Also, I have added an error message that returns 400: “Darth Vader cannot create an order.”, if the name value in the incoming PeopleResponse object is Darth Vader. Response Example appears below.
Let’s say I deploy this API in an isolated environment. When I send request the /createOrder endpoint, it will send a request to the swapi, but since the swap is not found in this isolated environment, it will get an error, so I will not be able to check whether my API is working correctly. I need to mock the swapi so I can check if it works correctly. Here wiremock comes to our rescue.
Wiremock is a library that can be used to mock web services. It is easy to use. It looks at http://localhost:8083/, which I deployed from docker with the command below.
docker run -it — rm -p 8083:8083 wiremock/wiremock — port 8083
In the basic-order-API project, I write http://localhost:8083/ as baseUrl variable at the createSwapiService method. This method uses retrofit and returns swapiService. Thanks to Wiremock, I will simulate a call to the /people/{customer_id} endpoint.
For this, I first create the basic-order-API-acceptance-test project. I add the models that use in our API to this project. Here I am calling our API using RestAssured. Then I start writing my tests. I have 2 tests, shouldCreateOrder and shouldNotCreateOrderWhenPeopleIsDarthVader. For the API to work properly here, for example, when I send peopleId 1 in my OrderRequest, I need to create a People response object at http://localhost:8083/people/1 in wiremock. I do this with the method I wrote below. I specify that I will create a mock with the StubFor method. In the get method, I give the endpoint to which I will return, and in the willReturn method, there is the HTTP status code value that I want to return withStatus, the Header value to which I will return withHeader and the Body value to which I will return withBody.
If there are special cases that I want to cover with the mock here, I can handle that too. If you remember, in our API, if the person's name is DarthVader, “Darth Vader cannot create an order.” I wrote a control that sends a message and returns 400. To test this, I added a boolean isDarthVader control to the method, if this value is true, Darth Vader is set to the name value in the PeopleResponse, so I can handle this situation.
In our shouldCreateOrder test, I send the isDarthVader flag false to the mock, so because of the randomDataProvider I wrote, a PeopleResponse whose name is Luke Skywalker returns, and when I call our ap, I see that the peopleResponse returns 200 and my other assertions are passed.
]
In our shouldNotCreateOrderWhenPeopleIsDarthVader test, I return the above-mentioned isDarthVader flag true, so I assert that 400 is returned from our API and the message value of ErrorResponse is “Darth Vader cannot create order”.
If I want to see the response object returned by wiremock on localhost, I can see the object created by entering the value http://localhost:8083/people/{peopleId} into my browser.
I go to http://localhost:8083/__admin/mappings to see all the mocks that have been created.
For more detailed information about Wiremock, you can check https://wiremock.org/docs.
As an example of the difficulties that mocking will create, we can give the change of the contract of the objects we mocked. In this case, according to our mock-up, the API will continue to work in the isolated environment, but will receive an error in the environment where the real dependency is present. To prevent this situation, we should write a contract test. When the contract test fails, we notice a change in the models of the relevant API.
I tried to give information about the logic of mocking and the use of Wiremock in a simple way, I hope it was useful. Take care and see you in my next post.
Resources:
https://en.wikipedia.org/wiki/Mock_object https://wiremock.org/docs/stubbing/