2

I have been reading into python mocking but can't get my head around why the following code is failing.

I have two classes, a Potato and a PotatoBag like the following. Figure is stored in food.py and Report is stored in bag.py.

class Potato:
    def create_potato(self):
        pass

    def output_potato(self):
        pass


class PotatoBag:
    def __init__(self, potatoes):
        self.potatoes = potatoes

    def output_to_file(self):
        for fig in self.potatoes:
            fig.create_potato()
            fig.output_potato()

Currently I am trying to unit test the output method so that Report correctly calls create_figure and output_figure from Figure using a mock. This is my test code:

from unittest.mock import MagicMock, patch
from bag import PotatoBag
from food import Potato
import pytest

@pytest.fixture(scope='module')
def potatoes():
    x = Potato()
    y = Potato()
    return [x, y]

@patch('food.Potato')
def test_output_to_file(mock_potato, potatoes):

    test_potato_bag = PotatoBag(potatoes)
    test_potato_bag.output_to_file()

    mock_potato.return_value.create_potato.assert_called()
    mock_potato.return_value.output_potato.assert_called()

Immediately pytest yields an AssertionError stating that create_figure was never called.

_mock_self = <MagicMock name='Potato().create_potato' id='140480853451272'>

    def assert_called(_mock_self):
        """assert that the mock was called at least once
            """
        self = _mock_self
        if self.call_count == 0:
            msg = ("Expected '%s' to have been called." %
                   self._mock_name or 'mock')
>           raise AssertionError(msg)
E           AssertionError: Expected 'create_potato' to have been called.

/home/anaconda3/lib/python3.7/unittest/mock.py:792: AssertionError

What is wrong with my code?

1 Answer 1

3

You are passing the Report a list of Figures from your fixture instead of a mock.

Changing your test to...

@patch('figure.Figure')
def test_output_to_file(mock_figure, figures):

    test_report = Report([mock_figure])
    test_report.output_to_file()

    mock_figure.create_figure.assert_called_once()
    mock_figure.output_figure.assert_called_once()

This resolves testing that output_to_file correctly is calling the functions on Figure without actually worrying about setting up a figure and dealing with any side effects or additional complexities that may come with calling those functions. The worries of that can be saved for the unit tests for Figure ;)

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.