isinstance and Mocking
mocking, python, unit-testing
Solution
Don't use `isinstance`, instead check for the existence of the `say_it` method. If the method exists, call it:
if hasattr(hw_obj, 'say_it'):
print hw_obj.say_it()
This is a better design anyway: relying on type information is much more brittle.
Problem
``` class HelloWorld(object): def say_it(self): return 'Hello I am Hello World' def i_call_hello_world(hw_obj): print 'here... check type: %s' %type(HelloWorld) if isinstance(hw_obj, HelloWorld): print hw_obj.say_it() from mock import patch, MagicMock import unittest class TestInstance(unittest.TestCase): @patch('__main__.HelloWorld', spec=HelloWorld) def test_mock(self,MK): print type(MK) MK.say_it.return_value = 'I am fake' v = i_call_hello_world(MK) print v if __name__ == '__main__': c = HelloWorld() i_call_hello_world(c) print isinstance(c, HelloWorld) unittest.main() ``` Here is the traceback ``` here... check type: <type 'type'> Hello I am Hello World True <class 'mock.MagicMock'> here... check type: <class 'mock.MagicMock'> E ====================================================================== ERROR: test_mock (__main__.TestInstance) ---------------------------------------------------------------------- Traceback (most recent call last): File "/usr/local/lib/python2.7/dist-packages/mock.py", line 1224, in patched return func(*args, **keywargs) File "t.py", line 18, in test_mock v = i_call_hello_world(MK) File "t.py", line 7, in i_call_hello_world if isinstance(hw_obj, HelloWorld): TypeError: isinstance() arg 2 must be a class, type, or tuple of classes and types ---------------------------------------------------------------------- Ran 1 test in 0.002s ``` Q1. Why is this error thrown? They are `<class type='MagicMock>` Q2. How do I pause the mocking so that the first line will pass if the error is fixed? From the docs: Normally the `__class__` attribute of an object will return its type. For a mock object with a spec, `__class__` returns the spec class instead. This allows mock objects to pass `isinstance()` tests for the object they are replacing / masquerading as: ``` mock = Mock(spec=3) isinstance(mock, int) True ```