This is part of the REST API Testing in Python series.
This post will show you how to build a dynamic REST API mock service with magic using Flask before_request decorator.
The traditional approach of mock service is to build a mock service for each endpoint, and for the same endpoint you need to modify the mock service when you want to test a different scenario, e.g. return an error instead of a successful response, not to mention different mocks for different request methods, i.e. GET, POST, PUT, etc. For instance, you may create a mock service with Postman as follows:
Let’s re-think the mock services, what you want to mock is Response Code and Response Body, and you want a special response for each of your test cases. Why not set the expected Response Code and Body in your requests then? Yep, that’s what I am going to demonstrate here.
Design
Use Flask before_request to mock any endpoints and any request methods. Note: This decorator function is called before handling a specific endpoint.
Send the response with the response_code and response_body set in the request headers.
Request Example:
GET http://127.0.0.1:5000/anyendpoint
Response-Code: 202
Response-Body: {"code": 0, "message": "all good"}
Response Example:
Status Code: 202
{"code": 0, "message": "all good"}
Implementation
First, install the required packages as follows.
pip install flask requests
The mock service is just 15 lines of code. Let’s dive into it directly.
The code itself is quite self-explainable, the power of Python 😊. We set the response code to default 200 if it is not set in the request headers (line #8), and return a warning message to the client if the response body is not set (line #11). That’s it!
Start the mock service with python flask_mock_dynamic.py
and you are ready to roll.
A quick test is to visit http://127.0.0.1:5000/anyendpoint in your web browser and you will see this:
With requests, we can write a proper pytest test case as follows.
Just run pytest
in the same folder or pytest test_mock_service_dynamic.py
for the test and you will see results as below. test_mock_service_dynamic.py::test_mock_service_dynamic PASSED
Change the headers or assert to play around and you will see the power of the magic.
You can also use my test framework mentioned in REST API Testing in Python for a more comprehensive usage.
Further
Alternatively, you can set a ‘response_file’ header in the request and read the expected response from a file. Or if it is inconvenient to set additional headers in your test or application code, you can build a ‘set_response’ endpoint in the mock service so that you can call this endpoint to set the expected response before calling the test endpoint.