[TIP] Mocking and patching a class with mock.py?
Daryl Spitzer
daryl.spitzer at gmail.com
Sun Jan 20 14:39:19 PST 2008
I just started using Michael's mock.py (version 0.3.1) and I'm pleased
that I've been able to remove many lines from my test code and make it
more readable.
But I'm stuck trying to patch a class with a mock. I think some
sample code would better explain my problem:
doessomething.py:
-----
class MyClass(object):
def do_something(self, arg):
print 'arg:', arg
def does_something():
obj = MyClass()
obj.do_something('x')
if __name__ == "__main__":
does_something()
-----
doessomething_test.py
-----
import doessomething
import unittest
from mock import Mock, patch
class TestDoessomething(unittest.TestCase):
mock = Mock(spec=doessomething.MyClass)
@patch('doessomething', 'MyClass', mock)
def test_does_something(self):
doessomething.does_something()
self.assertEqual(mock.do_something.call_args_list,
[(('x',), {})])
if __name__ == "__main__":
unittest.main()
-----
When I run `python doessomething.py`, I get "arg: x" as expected.
When I run `python doessomething_test.py`, I get "AttributeError:
'NoneType' object has no attribute 'do_something'" on
"obj.do_something('x')" in doessomething.py.
Does what I'm trying to do (replace MyClass in doessomething.py) with
a mock make sense? Can it be done with the Mock.__init__() spec
argument?
I tried the following version of TestDoessomething (in
doessomething_test.py), but get the same error:
-----
class TestDoessomething(unittest.TestCase):
def test_does_something(self):
mock = Mock(spec=doessomething.MyClass)
try:
old_my_class = doessomething.MyClass
doessomething.MyClass = mock
doessomething.does_something()
self.assertEqual(mock.do_something.call_args_list,
[(('x',), {})])
finally:
doessomething.MyClass = old_my_class
-----
So the problem is must be a misunderstanding of (or possibly a bug in)
how the spec argument works with classes.
--
Daryl Spitzer
More information about the testing-in-python
mailing list