Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mock.patch() not patching class who called a couples of levels inside function call

I have a task

def task():
   a = worker()
   a.do_some_work()

Worker itself is a separate class in separate module, who use Driver class like that,

class Worker(object):
   def __init__(self):
     self.driver = Driver(args)
     ...

and once again Driver is a separate class in separate module

so when I trying something like

with patch('package.module.Driver', new=Mock(return_value=999)):
   task()

in task there is still a Driver class instance, but not a mock. That's wrong. How to fix that?

UPD1: Driver and Worker live in different modules and Worker import Driver

like image 331
Ph0en1x Avatar asked Aug 26 '14 15:08

Ph0en1x


People also ask

What does mocker patch do?

patch() unittest. mock provides a powerful mechanism for mocking objects, called patch() , which looks up an object in a given module and replaces that object with a Mock . Usually, you use patch() as a decorator or a context manager to provide a scope in which you will mock the target object.

What is the difference between mock and patch?

Mock is a type, and patch is a context. So you are going to pass or receive Mock instances as parameters, and apply patch contexts to blocks of code. (Lowercase 'mock' is just the name of the package.) Tests and test classes are often decorated with calls to patch.

How do I apply a patch in Python?

Mocking in Python is done by using patch to hijack an API function or object creation call. When patch intercepts a call, it returns a MagicMock object by default. By setting properties on the MagicMock object, you can mock the API call to return any value you want or raise an Exception .

How do you mock a class object in Python?

The patch() decorators makes it easy to temporarily replace classes in a particular module with a Mock object. By default patch() will create a MagicMock for you. You can specify an alternative class of Mock using the new_callable argument to patch() . Create a new Mock object.


1 Answers

Your MyProject.Workers.base module imported Driver as a global:

from MyProject.utils.drivers import Driver

This is a new, separate reference to the Driver class. If you now patch MyProject.utils.drivers.Driver, the Worker class will not see the patched object; as it'll use it's own global reference.

Patch the global Worker actually uses:

with patch('MyProject.Workers.base.Driver', new=Mock(return_value=999)):
    task()

See the Where to patch section of the mock documentation.

like image 197
Martijn Pieters Avatar answered Nov 14 '22 22:11

Martijn Pieters