26

I am trying to test a method that within it creates an instance of another class, I am attempting to mock the creation of the inner class... That is not working for me. I tried replicating the problem to a simplified case - and still no go. Here is the simplified case:

I have a directory named pymock with a __init__.py in it. Other than that there are these 3 files:

foo.py

#!/usr/bin/python
class Foo(object):
    def foo1(self):
        return 1

goo.py

#!/usr/bin/python
from foo import Foo


class Goo(object):
    def goo1(self):
        f = Foo()
        return f.foo1()

goo_test.py

#!/usr/bin/python
from mock import patch, Mock
from nose.tools import assert_equal

from goo import Goo


class TestGoo(object):
    def setup(self):
        self.goo = Goo()

    @patch('pymock.foo.Foo', autospec=True)
    def test_goo1(self, foo1_mock):
        foo_instance = Mock()
        foo1_mock.return_value = foo_instance
        foo_instance.foo1.return_value = 11
        assert_equal(11, self.goo.goo1())

Thanks in advance!

2 Answers 2

28

You need to patch the name that goo is using.

@patch('pymock.goo.Foo', autospec=True)
Sign up to request clarification or add additional context in comments.

7 Comments

Doesn't seem right. Anyway I tried - got ImportError: No module named goo
I wasn't sure if it needed the pymock as `well.
mock.patch replaces the object that a name refers to, and pymock.foo.Foo is the name that your test module uses to access that function. Python has no true global variables; the goo module has its own reference to foo.Foo that its functions use, so that is the name you need to patch.
Oh my jesus I was stuck on this for a day and this clicked it for me - don't patch the source of the method: @patch('djang.some.lib.get_template') - patch where it's being used @patch('my_project.email.get_template'). Game changer.
@chepner, your third comment should be part of the answer, imo. It does a great job at explaining why the answer is correct, as it applies to methods as well.
|
15

Basically it's how you import functions/classes. In goo.py you've imported Foo directly. So goo.py has it's own reference to Foo, so your patch will have to be: @patch('pymock.goo.Foo', autospec=True)

But if goo.py looked like this:

#!/usr/bin/python
import foo


class Goo(object):
    def goo1(self):
        f = foo.Foo()
        return f.foo1()

the patch in your question would work since goo.py doesn't have a direct reference to Foo

1 Comment

Fantastic explanation of the why, @cberenik. You helped me out of a pinch here, so thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.