The code discussed in this post can be found in the github repository.
While writing a module to handle Google ClientLogin recently, I wanted to test error handling by simulating error
responses from the server. A simple but powerful way of doing this is to use the
patching ability of the mock
module.
The patching ability allows you to replace objects in scope with mocks so that different side effects or return values can be defined. Note that ‘object’ is used here in the pythonic sense – referring to entities such as modules and functions as well as class instances.
This is best illustrated by a real example, so in this post we’re going to mock the requests
module and generate
the exceptions described in the
documentation when a request is made.
Our example module sends credentials to Google’s ClientLogin service in order to receive an authentication token, required for accessing certain Google services (such as C2DM). If you are interested, you can read more about ClientLogin on the Google Code page.
So, to request an authentication token from the ClientLogin service, you POST
a set of parameters including email and password to the service endpoint. Here is a cut-down version of the code that initiates the authentication request:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
If the requests.post
method throws an exception, we simply raise
it to the caller rather than handling it immediately.
In the requests
module, RequestException
is the base class from which others (like ConnectionError
) inherit. We could improve our approach to exception handling but it is sufficient for this example.
These exceptions will be thrown from our mocked class, which is patched into the above code using a context manager:
1 2 3 4 5 6 7 8 9 10 11 |
|
Here, we have patched the post
method in the requests
module to throw a ConnectionError
. You can think of this like code injection, where with
acts as the closure.
In the real test method, we assert the exception was raised with another context manager:
1 2 3 4 5 |
|
Here, we assert that the ConnectionError
exception is raised to the caller, but we could easily have asserted a different condition. We could, for instance, have verified some exception handling logic.
As we’ve seen, mocking objects and methods in this manner is a simple but powerful way of running your code under different simulated conditions, allowing thorough testing of error-handling logic.
You can see the full module including tests and usage instructions at the github repository. For more information on the mock
module, the full documentation is available.