Kamyar Souri
Kamyar Souri

Reputation: 1923

Mock a class in python

I am trying to create a mock for the class vBundle. Here is how I did it:

from vBundle import vBundle

@mock.patch('vBundle')
def test_one_job_end_to_end(self, vBundle_mock):        
    vBundle_mock.return_value.download_bundle.side_effect = vBundle_download_bundle_mock_01
    bundle = vBundle()
    bundle.download_bundle('456', '/tmp/')

When I run the code I get the following error:

File "/Users/user/Library/Python/2.7/lib/python/site-packages/mock/mock.py", line 1670, in patch
    getter, attribute = _get_target(target)
  File "/Users/user/Library/Python/2.7/lib/python/site-packages/mock/mock.py", line 1522, in _get_target
    (target,))
TypeError: Need a valid target to patch. You supplied: 'vBundle'

Question: Why vBundle is not a valid target? What should I put in @mock.patch to correctly refer to vBundle?

Upvotes: 1

Views: 1126

Answers (1)

yorodm
yorodm

Reputation: 4461

From the docs:

target should be a string in the form 'package.module.ClassName'. The target is imported and the specified object replaced with the new object, so the target must be importable from the environment you are calling patch() from. The target is imported when the decorated function is executed, not at decoration time.

In your sample code, vBundle is imported so the name vBundle is now in the current module (a.k.a myModule.vBundle)

from vBundle import vBundle

@mock.patch('mymodule.vBundle')
def test_one_job_end_to_end(self, vBundle_mock):        
    vBundle_mock.return_value.download_bundle.side_effect = vBundle_download_bundle_mock_01
    bundle = vBundle()
    bundle.download_bundle('456', '/tmp/')

The other alternative would be to just impor the vBundle module (not the class) and apply a patch to vBundle.vBundl. Remember that you need a full target name to patch, so the module name is needed.

Upvotes: 1

Related Questions