Python 2.7 mock/patch: understanding assert_called_XYZ()
mocking, python, python-2.7, unit-testing
Solution
The method `assert_called_once` does not exist and it does not perform an assertion. It's no different from writing `StringIOMock.assert_foo_bar_does_not_exist()` or any other method. The mock library doesn't check whether the method called on the mock actually exists.
If you use `assert_called_once_with` then it fails as expected.
You can use the `spec` parameter to raise an error when you call a non-existent method:
@patch("StringIO.StringIO", spec=StringIO.StringIO)
def testSomethingNotWorkingAsExpected(self, StringIOMock):
StringIOMock.assert_called_once() # will fail as the method doesn't exist
Problem
I'm relatively new to Python and unit testing in Python. From the Java world I know the concept of mocking but it seem to be much different from what I can see in Python. I found this guide, which I found very helpful: http://www.voidspace.org.uk/python/mock/index.html But as I wrote my (a bit more complex) tests with mocked out dependencies I noticed a strage behavior. I decided to create a reduced, simple example which also does not work as I expect it. Take a look at this, the result and my expectation I have added as comments: ``` import unittest from mock import patch, Mock, MagicMock class BasicTest(unittest.TestCase): @patch("StringIO.StringIO") def testSomethingNotWorkingAsExpected(self, StringIOMock): StringIOMock.assert_called_once() # asserts, but why? @patch("StringIO.StringIO") def testSomethingSomehowWorking(self, StringIOMock): # self.instantiateStringIO() # intentionally commented out assert StringIOMock.called # does not assert (leading to failure of this test); as expected. If the above line is not commented, this asserts as expected. def instantiateStringIO(self): import StringIO StringIO.StringIO() ``` Why is `assert_called_once()` asserting the instantiation of `StringIO` even it has not been instantiated yet? And why does `assert ClassMock.called` bring the expected results? Using `assert not ...` to assert a method has not been called I found here: Assert a function/method was not called using Mock. I inverted this pattern in my case by omitting the `not`. Somewhere I found the pattern `ClassMock.return_value` to reference an instance. But I understand this as a way to manupulate the instance of a Mock before it will be called, not as a way to access the instance that might an underliing code have internally created. Or am I wrong? My environment: - Python 2.7.3 - mock 0.8.8 - Fedora 19 Probably my understanding of the mock/patch thing is wrong. Could please someone aditionally explain what a class mock does and how it works? Edit1: Added output ... and added paraphrase in parens to comment in `testSomethingSomehowWorking` This is the output: ``` .F ====================================================================== FAIL: testSomethingSomehowWorking (test_test.BasicTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/usr/lib/python2.7/site-packages/mock.py", line 1224, in patched return func(*args, **keywargs) File "test_test.py", line 15, in testSomethingSomehowWorking assert StringIOMock.called # does not assert; as expected AssertionError ---------------------------------------------------------------------- Ran 2 tests in 0.001s FAILED (failures=1) ```