简体   繁体   中英

python unittest.mock.patch strange behaviour

I use unittest in my testing. I import a class in yhab.main package as...

from yhab.blah import SomeClass

def some_func():
    some_instance = SomeClass()
    return some_instance.method()

yhab.blah.SomeClass is defined as...

class SomeClass:
    def method(self):
        return 'hello'

And then I write a test like this...

@mock.patch('yhab.blah.SomeClass')
def test_mock_of_blah_someclass(mock_some_class):
    assert some_func() != 'hello'

the invocation of method() calls the real instance, not a mock.

But if I do this...

@mock.patch('yhab.main.SomeClass')
def test_mock_of_main_someclass(mock_some_class):
    assert some_func() != 'hello'

the invocation of method() calls the mock, not the real instance and the test passes.

Why is that?

I was thinking that python must make some sort of copy of the class definition when an import happens, but I wrote a test that proves that to not be the case.

The docs say the following, which kind of eludes to this, but it doesn't really say it outright, and IMO doesn't really explain it, especially for a python newb...

Patching a class replaces the class with a MagicMock instance. If the class is instantiated in the code under test then it will be the return_value of the mock that will be used .

Do the docs need to be updated to be clear?

After you import SomeClass from yhab.blah , it ends up in the yhab.main namespace, not in the yhab.blah namespace.

Try to use @mock.patch('yhab.main.SomeClass') instead of @mock.patch('yhab.blah.SomeClass') .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM