[TIP] I don't get it?

Michael Foord fuzzyman at voidspace.org.uk
Tue Nov 2 09:49:07 PDT 2010


On 02/11/2010 16:43, WW wrote:
> On Tue, Nov 2, 2010 at 12:17 PM, Michael Foord 
> <fuzzyman at voidspace.org.uk <mailto:fuzzyman at voidspace.org.uk>> wrote:
>
>     On 02/11/2010 15:34, WW wrote:
>>     Hello,
>>
>>     This is my first time using the python mock library and I'm a
>>     little confused.  I'd like to provide some guarantees that my
>>     mocks are being called with the correct number of arguments.  The
>>     documentation seems to indicate there are two ways to do this,
>>     "spec" and "mocksignature", but it's a little unclear to me what
>>     the difference is supposed to be between them.
>>
>>     I find myself using the @patch.object decorator almost all the
>>     time, because the modules I'm testing use a lot of top-level
>>     functions from modules they've imported.  When I do something
>>     like this:
>>
>>     @patch.object(somemodule, 'somemethod', spec=True)
>>
>
>     You should still be able to use patch with a named function (as a
>     string). See the other replies for an example.
>
>
> Does this work if I'm trying to patch a global variable rather than a 
> function in another module?

You mean a global variable in the current module? If so then still yes.

@patch('%s.function' % __name__, mocksignature=True)
def test_something(self, mockfunction):
     ...


>
>>     It doesn't seem to have any effect; I can call
>>     somemodule.somemethod with any combination of invalid arguments
>>     and no exceptions are thrown. 
>
>     Using spec doesn't protect you against being called with invalid
>     arguments. You should get an error when you validate that the
>     calls were made correctly when you call 'assert_called_with'.
>
>
> assert_called_with is fine if I know the exact values I want the 
> function to be called with, but I'm just trying to make sure that a 
> function was called with the correct number of arguments.  If spec 
> can't do this, then what is spec supposed to be used for?  I'm still 
> unclear as to what the difference is between spec and mocksignature 
> and why both exist.

spec is not for mocking functions (mocksignature is). Spec is for 
mocking out classes / objects to check that only methods / attributes 
that exist on the spec object are used. Accessing other attributes will 
raise an AttributeError.

All the best,

Michael Foord

>>     However, when I do:
>>
>>     @patch.object(somemodule, 'somemethod', mocksignature=True)
>>
>>     I get:
>>
>>     Traceback (most recent call last):
>>       File "/usr/lib/python2.6/site-
>>     packages/mock-0.7.0b3-py2.6.egg/mock.py", line 485, in patched
>>         arg = patching.__enter__()
>>       File
>>     "/usr/lib/python2.6/site-packages/mock-0.7.0b3-py2.6.egg/mock.py", line
>>     536, in __enter__
>>         new_attr = mocksignature(original, new)
>>       File
>>     "/usr/lib/python2.6/site-packages/mock-0.7.0b3-py2.6.egg/mock.py", line
>>     140, in mocksignature
>>         signature, func = _getsignature(func, skipfirst)
>>       File
>>     "/usr/lib/python2.6/site-packages/mock-0.7.0b3-py2.6.egg/mock.py", line
>>     87, in _getsignature
>>         func = func.__call__
>>     AttributeError: 'SentinelObject' object has no attribute '__call__'
>>
>
>     This is weird. The traceback implies that you are trying to
>     replace a sentinel object using mocksignature (and sentinels don't
>     have signatures to mock). Either that or it is a bug. I'll create
>     a simple test case here (but this functionality *is* tested), but
>     it looks like something is not quite setup how you expect.
>
>
> Here's a small test case that produces the error in Python 2.6, CentOS 
> 5.5:
>
>   1.
>       from mock import patch
>   2.
>   3.
>       class tc(object):
>   4.
>           def meth(a, b, c):
>   5.
>               pass
>   6.
>   7.
>       g = tc()
>   8.
>   9.
>       @patch.object(g, 'meth', mocksignature=True)
>  10.
>       def test_g(patched):
>  11.
>           g.meth(1)
>  12.
>  13.
>       test_g()
>
>
>
>     All the best,
>
>     Michael Foord
>
>
> Likewise.
>
>>     What am I missing here?
>>
>>     Thanks for your help.
>>
>>
>>     _______________________________________________
>>     testing-in-python mailing list
>>     testing-in-python at lists.idyll.org
>>     <mailto:testing-in-python at lists.idyll.org>
>>     http://lists.idyll.org/listinfo/testing-in-python
>
>
>     -- 
>     http://www.voidspace.org.uk/
>
>


-- 

http://www.voidspace.org.uk/

READ CAREFULLY. By accepting and reading this email you agree,
on behalf of your employer, to release me from all obligations
and waivers arising from any and all NON-NEGOTIATED agreements,
licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap,
confidentiality, non-disclosure, non-compete and acceptable use
policies ("BOGUS AGREEMENTS") that I have entered into with your
employer, its partners, licensors, agents and assigns, in
perpetuity, without prejudice to my ongoing rights and privileges.
You further represent that you have the authority to release me
from any BOGUS AGREEMENTS on behalf of your employer.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.idyll.org/pipermail/testing-in-python/attachments/20101102/3a6f87c9/attachment.htm>


More information about the testing-in-python mailing list