[TIP] mock can't address a class by class name

Julian Berman julian at grayvines.com
Wed Dec 12 14:53:36 PST 2012


On Wednesday, December 12, 2012, Yang wrote:

> if I have mymodule.py:
>
> class MyClass:
>        def run():
>              return 1
>
>
>
> then I try to mock it in test:
>
>
> with patch('mymodule.MyClass') as mock:
>       instance = mock.return_value
>
>       mock.run.return_value =2
>
>
> this works fine. but if in my test code, I import the MyClass first:
>
> from mymodule import MyClass
>
> with patch('MyClass') as mock:
>  ......
>
> it fails to find 'MyClass'
>
>
Correct. patch takes the fully qualified absolute name of an object
(consider what would happen if it didn't, and you had an object and module
with the same name, besides the fact that patch is a bit hard to
grasp already without it searching locals first). If you want to patch
objects in the current module, you'd use "mymodule.MyClass" as you have
above (or patch.object with the module object, which I prefer anyhow).
That's almost certainly not what you want though, since your local scope is
your testing module, when you need to be patching in the module under test.


>
> even more serious is that if I refer to the mock class with full name
> mymodule.Myclass in the patch() line, but the production code refers to it
> as simply Myclass after importing it first, the mock does not take effect,
>  so I have to modify production code to mock it out. this completely does
> not work for real testing cases.
>

Mock isn't (too) magical. It just replaces names in the scope you tell it
to. So if you have a name "MyClass" in mymodule, mock can patch that to
refer to a different object if you patch in the correct location the
correct name. Otherwise, it won't know what you're referring to.

You shouldn't have to modify production code certainly. The only way you'd
fail here presuming you patched in the right place (in mymodule as
above) would be if some object already had / kept a reference to the real
object by the time you patched, which shouldn't be happening under normal
circumstances, but if it did you'd want to patch that object's attr too.


Hope this helps,
Julian
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.idyll.org/pipermail/testing-in-python/attachments/20121212/40cf167d/attachment.htm>


More information about the testing-in-python mailing list