Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mock objects of a Python class?

Lets say I the following class;

class CompositionClass(object):
    def __init__(self):
        self._redis = Redis()
        self._binance_client = BinanceClient()

    def do_processing(self, data):
        self._redis.write(data)
        self._binance_client.buy(data.amount_to_buy)

        # logic to actually unittest

        return process_val

I have other objects which call external API as composition in my ComplexClass. When I am unittesting the logic of do_processing, I do not want to call these expensive API calls. I have checked throughly in SO and Google about unittesting; all examples are simple not that really useful. In my case how can I use unittest.mock to mock these objects?

like image 810
Vino Avatar asked May 11 '18 14:05

Vino


1 Answers

One way of mocking the Redis and BinanceClient classes is to use the patch decorator in your test class, such as:

from unittest import TestCase
from unittest.mock import patch
from package.module import CompositionClass

class TestCompositionClass(TestCase):

    @patch('package.module.BinanceClient')
    @patch('package.module.Redis')
    def test_do_processing(self, mock_redis, mock_binance):
        c = CompositionClass()
        data = [...]
        c.do_processing(data)

        # Perform your assertions

        # Check that mocks were called
        mock_redis.return_value.write.assert_called_once_with(data)
        mock_binance.return_value.buy.assert_called_once_with(data.amount_to_buy)

Note that the path specified to @patch is the path to module containing the CompositionClass and its imports for Redis and BinanceClient. The patching happens in that module, not the module containing the Redis and BinanceClient implementations themselves.

like image 85
Will Keeling Avatar answered Oct 14 '22 05:10

Will Keeling