Introduction to Mocking in Python

Mocking is a library for testing in Python. It allows you to replace parts of your system under test with mock objects and make assertions about how they have been used. This tutorial will discuss in detail what mocking is and how to use it in Python applications.

What Is Mocking?

Mocking is a library for testing in Python which allows you to replace parts of your system under test with mock objects and make assertions about how they have been used.

In Python, mocking is accomplished by replacing parts of your system with mock objects using the unittest.mock module. This module contains a number of useful classes and functions, namely the patch function (as decorator and context manager) and the MagicMock class. These two components are very important in achieving mocking in Python.

A mock function call usually returns a predefined value immediately. A mock object’s attributes and methods are defined in the test as well, without creating the real object.

Mocking also allows you to return predefined values to each function call when writing tests. This allows you to have more control when testing.

Prerequisites

Mock is available in Python 3, but if you are using a Python version below

3.3, you can still use unittest.mock
by importing it as a separate library like so.

$ pip install mock

Benefits of Mocking

Some of the benefits of mocking include:

  1. Avoiding overdependence.
    Mocking reduces the dependence of functions. For instance, if you have a function A class that depends on a function B, you will need to write a few unit tests covering the features provided by function B. Let’s say the code grows in future and you have more functions, i.e. A depends on B, B depends on C, and C depends on D. If a fault is introduced in Z, all your unit tests will fail.
  2. Reduced overload.
    This applies to resource-intensive functions. A mock of that function would cut down on unnecessary resource usage during testing, therefore reducing test run time.
  3. Bypass time constraints in functions.
    This applies to scheduled activities. Imagine a process that has been scheduled to execute every hour. In such a situation, mocking the time source lets you actually unit test such logic so that your test doesn’t have to run for hours, waiting for the time to pass.

Usage of mock
is simple as:

>>> from mock import Mock
>>> mock = Mock(return_values = 10)
>>> mock(1,4,foo ='bar')

>>> mock.return_values
10

Here, we import the mock module, create a mock object, and specify return values. When the mock object is called, we want it to be able to return some values. In our case, we want the mock object to return a value of 10. If we call the mock object with the arguments (1, 4, foo ='bar')
, the result will be the value 10, which was defined as a return value.

You can also raise exceptions inside mocks as follows:

>>> mock = Mock(side_effect=KeyError('foobar'))
>>> mock()
Traceback (most recent call last):
 ...
KeyError: 'foobar'

The side_effects
argument allows you to perform certain things like raising an exception when a mock is called.

Example

Consider this simple function:

import requests


def api():
    response = requests.get('https://www.google.com/')
    return response

This function performs an API request to the Google webpage and returns a response.

The corresponding simple test case will be as follows:

import unittest
from main import api


class TetsApi(unittest.TestCase):

    def test_api(self):
        assert api() == 200

Running the above test should give an output like so:

----------------------------------------------------------------------
Ran 1 test in 3.997s

OK

Let’s introduce mocking to this example, and the resulting test with the Mock module will be as shown below:

import unittest
from mock import Mock
from mock import patch
import requests
import unittest



class TetsApi(unittest.TestCase):

    def test_api(self):
        with patch.object(requests, 'get') as get_mock:
            get_mock.return_value = mock_response = Mock()
            mock_response.status_code = 200
            assert api() == 200

Running the above test should give an output like so:

----------------------------------------------------------------------
Ran 1 test in 0.001s

OK

As seen above, the mocking module takes less time to make the same API call as the normal test case.

Larger Example

Let’s assume you have a script that interacts with an external API and makes calls to that API whenever a certain function is called. In this example, we are going to use the Twitter API to implement a Python script which will post to the Twitter profile page.

We don’t want to post messages on Twitter every time we test the script, and that’s where Mocking comes in.

Let’s get started. We will be using the python-twitter library, and the first thing we will do is create a folder python_mock
and, inside the folder, create two files, namely tweet.py
and mock_test.py
.

Write the following code to the file tweet.py
.

# pip install python-twitter
import twitter

# define authentication credentials
consumer_key = 'iYD2sKY4NC8teRb9BUM8UguRa'
consumer_secret = 'uW3tHdH6UAqlxA7yxmcr8FSMSzQIBIpcC4NNS7jrvkxREdJ15m'
access_token_key = '314746354-Ucq36TRDnfGAxpOVtnK1qZxMfRKzFHFhyRqzNpTx7wZ1qHS0qycy0aNjoMDpKhcfzuLm6uAbhB2LilxZzST8w'
access_token_secret = '7wZ1qHS0qycy0aNjoMDpKhcfzuLm6uAbhB2LilxZzST8w'


def post_tweet(api, tweet):
    # post tweet
    status = api.PostUpdate(tweet)
    return status


def main():

    api = twitter.Api(consumer_key=consumer_key,
                      consumer_secret=consumer_secret,
                      access_token_key=access_token_key,
                      access_token_secret=access_token_secret)

    message = raw_input("Enter your tweet :")

    post_tweet(api, message)


if __name__ == '__main__':
    main()

In the code above, we first import the Twitter library and then define the authentication credentials, which you can easily get from the Twitter Apps page
.

The Twitter API is exposed via the twitter.Api
class, so we create the class by passing our tokens and secret keys.

The post_tweet
function takes in an authentication object and the message and then posts the tweet to the Twitter profile.

We then go ahead and mock the API call to Twitter so that the API doesn’t post to Twitter every time it is called. Go ahead and open the mock_test.py
file and add the following code.

# mock_test.py

#!/usr/bin/env python
import unittest
from mock import Mock


import tweet


class TweetTest(unittest.TestCase):

    def test_example(self):
        mock_twitter = Mock()
        tweet.post_tweet(
            mock_twitter, "Creating a Task Manager App Using Ionic: Part 1")
        mock_twitter.PostUpdate.assert_called_with(
            "Creating a Task Manager App Using Ionic: Part 1")


if __name__ == '__main__':
    unittest.main()

Running the above test should give an output like so:

----------------------------------------------------------------------
Ran 1 test in 0.001s

OK

Conclusion

This tutorial has covered most of the fundamentals of mocking and how to use mocking to perform external API calls. For more information, visit the official Python mocking documentation
. You can also find additional resources on authentication with the Twitter API in this tutorial.

Additionally, don’t hesitate to see what we have available for sale and for study in the Envato Market
, and please go ahead and ask any questions and provide your valuable feedback using the feed below.

Nettuts+稿源:Nettuts+ (源链) | 关于 | 阅读提示

本站遵循[CC BY-NC-SA 4.0]。如您有版权、意见投诉等问题,请通过eMail联系我们处理。
酷辣虫 » 综合技术 » Introduction to Mocking in Python

喜欢 (0)or分享给?

专业 x 专注 x 聚合 x 分享 CC BY-NC-SA 4.0

使用声明 | 英豪名录