Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper way to mock classes and assert on calls to methods

I am trying to write unit tests for Bar that makes calls to Foo's method read(). I have added the patch command in setUp() because other tests will use this patch as well.

Question

How can I check that the read() function was called with the arguments that I am expecting?

Code

foo.py
class Foo(object):
    def __init__(self):
        self.table = {'foo': 1}

    def read(self, name):
        return self.table[name]
bar.py
import foo

class Bar(object):
    def act(self):
        a = foo.Foo()
        return a.read('foo')
test_bar.py
import bar
import unittest
from mock import patch

class TestBar(unittest.TestCase):
    def setUp(self):
        self.foo_mock = patch('bar.foo.Foo', autospec=True).start()
        self.addCleanup(patch.stopall)

    def test_can_call_foo_with_correct_arguments(self):
        a = bar.Bar()
        a.act()
        self.foo_mock.read.assert_called_once_with('foo')

Output

python -m unittest discover
F
======================================================================
FAIL: test_can_call_foo_with_correct_arguments (test_bar.TestBar)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/test_dir/test_bar.py", line 12, in test_can_call_foo_with_correct_arguments
    self.foo_mock.read.assert_called_once_with('foo')
  File "/usr/local/lib/python2.7/dist-packages/mock.py", line 845, in assert_called_once_with
    raise AssertionError(msg)
AssertionError: Expected to be called once. Called 0 times.

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

FAILED (failures=1)
like image 890
jayant Avatar asked Dec 03 '15 13:12

jayant


People also ask

How do you mock another method in the same class which is being tested?

Instead of using mock(class) here we need to use Mockito. spy() to mock the same class we are testing. Then we can mock the method we want as follows. Mockito.

What is the difference between mock and MagicMock?

So what is the difference between them? MagicMock is a subclass of Mock . It contains all magic methods pre-created and ready to use (e.g. __str__ , __len__ , etc.). Therefore, you should use MagicMock when you need magic methods, and Mock if you don't need them.

What does @patch do Python?

patch() as a Decorator If you want to mock an object for the duration of your entire test function, you can use patch() as a function decorator. These functions are now in their own file, separate from their tests. Next, you'll re-create your tests in a file called tests.py .


1 Answers

read is a method on instances of Foo. You want to check for the mock return_value to access the instance. After all, you create the instance by calling foo.Foo():

foo_instance = self.foo_mock.return_value
foo_instance.read.assert_called_once_with('foo')

Note that you are patching foo.Foo; using bar.foo.Foo is the same object, but a round-about way of specifying it.

like image 131
Martijn Pieters Avatar answered Sep 19 '22 04:09

Martijn Pieters