[TIP] I don't get it?

WW teetee at gmail.com
Tue Nov 2 10:02:28 PDT 2010


You may have overlooked this from my earlier e-mail:

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()



On Tue, Nov 2, 2010 at 1:00 PM, Michael Foord <fuzzyman at voidspace.org.uk>wrote:

>  On 02/11/2010 16:57, WW wrote:
>
> Replacing "@patch.object(g, 'meth', mocksignature=True)" with
> "@patch('%s.g.meth' % __name__, mocksignature=True)" produces the same
> error.  Am I using this wrong?
>
>
> Is this the same traceback you posted earlier?
>
>
>     'SentinelObject' object has no attribute '__call__'
>
> Can you reproduce this with a minimal example? I've never seen that
> particular issue before.
>
>
>
> Thanks for the clarification regarding spec vs mocksignature.  So if I
> wanted to do both (a mock class that raises attribute errors when invalid
> attributes are accessed, but actual method attributes return methods that
> enforce the correct number of parameters), do I have to set that up
> manually, or does spec use mocksignature internally when returning attribute
> values?
>
>
> Using mocksignature changes the way that you access the mock. As the
> methods are replaced with 'real function objects' not mock objects as they
> normally are, you have to do it explicitly. You could create a utility
> function to auto patch out a mock with mocked-signatures.
>
> spec is purely about checking attribute access is valid.
>
>
> All the best,
>
> Michael Foord
>
> Thanks again...
>
> On Tue, Nov 2, 2010 at 12:49 PM, Michael Foord <fuzzyman at voidspace.org.uk>wrote:
>
>>  On 02/11/2010 16:43, WW wrote:
>>
>> On Tue, Nov 2, 2010 at 12:17 PM, Michael Foord <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.orghttp://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.
>>
>>
>
>
> --
> 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/d171a8bb/attachment-0001.htm>


More information about the testing-in-python mailing list