Service virtualization, Fakes, Stubs, Mocks, dummies etc are all different categories of Test Doubles which on broader level return a response for a given request in a controlled manner.
A request can be a method call, Object creation , database interaction or an webAPI interaction.
In below article we will be talking about API mocking and try to discuss some of what, why, how, when of API Mocks and also some challenges with them. If you are more concerned about the difference amongst all different types of Test Doubles then please head over here and here.
Enough said lets get started
What is Mocking
Mocks is nothing but an imitation(of what?). It simulates behaviour of real API but in a more a controlled manner.
A simple mock server consist of a server, which on matching certain request returns pre-defined response and other parameters associated such as response code, headers etc.
Why API Mocking
Getting quick and consistent feedback for a test are some of the key principles of continuous integration and API Mocks really help in facilitating this.
Quick feedback is very obvious, but lets understand.
Quicker the feedback of testing(either manual /automation) earlier bugs are caught and fixed. Have you been in a situation where a single test scenario take 15 min to complete with flaky payment service (roughly around 12 API calls), If yes embrace API Mocks.
What do we mean by “consistent/deterministic results”?.
Consider an airline booking application where we have to check whether user is able to
- Search for flight from PUN-DEL
- Select Seats for the passenger
- Add trip extras like “in-flight wifi” etc
- Complete Purchase
Over here search results, availability of seats and Trip Extras will vary depending on the current state of the flight, hence non deterministic tests.
But if we have mocked API responses for seat availability, then seat 25A will always be available.
Other benefits of API mocks are
- If we are doing visual comparison of screen, then data painted on each screen also needs to be consistent in order for visuals comparison to work.
- Validating manually scenarios when test environment is not available by pointing to Mocks.
- Validating issues(prod/new issue) with different version of apps by pointing to same mock environment.
- If backend and UI development are happening in parallel then UI needs a contract/dummy response to work with.
What to Mock?
As this article is pretty much about mocking backend, so yes backend should be mocked, but what if your team is owning some bit of backend(1 or 2 service) and UI.
Question to ask is
Should we mock backend APIs that we own or all the backend APIs to UI should be mocked.
If you are looking for a straight answers then “We should mock all the backend APIs of components which are owned by Team”. agree?
Let say team somehow agreed to approach where everything backend to UI will be mocked. Refer below
One fine day if SHIM layer owned by team is changed without making changes to UI then your UI test case will NOT raise any flags as they are always working with the mocked response and test will be returning false positives.
False positive is the last thing which you want in environment where confidence in automation test case is really crucial.
Food for thought : Is this problem with every API mocking(Let me know your thoughts in comments section, if yes how we can keep a check?)
How to API mock
First thing First : For mocking API, we need configuration in our app which can selectively point to mocks environment or live services based on the switch. It can be a javascript function which can change host & port or setting page in test builds for mobile app where one can select environment.
For writing mocks there are many open source tools available, personally I never felt the need to go for the paid solution for mocks or service virtualization.
Some of the popular open source solutions are wiremock, MounteBank. There is good documentation and “Getting Started” help available on respective tools website, but just to give glimpse how easy is to write mock for GET request, here is a snippet.
A simple mock GET request for “greet” in wiremock looks as follows
public class Test {
public static void main(String[] args){
stubFor(get(urlEqualTo("/greet"))
.willReturn(aResponse().withBody("Hello World")));
}
}
If responses are big then storing them in file and returning file content is something to consider.
Also mocked response can be templatized to include date sensitive responses like greet users with “todays date”.
public static void main(String[] args){
stubFor(get(urlEqualTo("/greet"))
.willReturn(aResponse().withBody("Hello World, today is:"+ DateTime.now())));
}
When to API mocks
It again depends upon the project, if we have agreed on why part of it, based on the automation need, it should be early in the project also if any of the backend service is flaky or slow then those should be mocked.
Challenges
As we have seen above API mocks really comes handy for UI automation and other manual scenarios but there are some challenges associated with it.
States in Mocks
Mocking gets more complex if we have states in our app for example : /greeting api will return “Hello World” and then on subsequent /greeting we need to return “Hello Universe”.
Great powers comes with great responsibilities
Also, this prevents parallelization of test cases as one fine day states will interfere and test will fail and debugging will take ages.
Stale mocks
As we discussed in what to mocks section, there are chances mocks will become stale and there is no clear way to know when they have become stale(unless clubbed with Contract tests) .
Templates
Templatization issues for Date time needs to be sorted very carefully, if UI tests and mocks are running in different timezones.
Broken Request
Consider a request with all mandatory objects
{
"action": "greet",
"name": "kapil",
"date": "2018-02-01"
}
In order to make mocks simple, quite many times mocks mapping for the above request would be something like
stubFor(post(urlEqualTo("/greet"))
.withRequestBody(containing("greet"))
.withRequestBody(containing("kapil"))
.willReturn(aResponse().withBody("Hello Kapil!")));
Now consider a scenario where there is a bug and mandatory “date” object is not coming in request, our UI automation test case will always pass again giving false positives.
Effort for mock updates
Last but not the least, effort required to update mocks(or automated way to do that) when backend changes is something to consider upfront and this is coming from an experience of working in project that has ~3000 mock responses.
And thats pretty much it, I hope this article has given insights in API mocking. Will be discussing about some challenges in follow up post. Do let me know your feedback in comment section, and if you like the article do share.
Top comments (0)