[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