[TIP] mock.patch in version 0.5 doesn't mock __exit__ method on open files
Michael Foord
fuzzyman at voidspace.org.uk
Mon Jul 13 07:33:12 PDT 2009
Matthew Wilson wrote:
> Thanks for the feedback!
>
> This patch below may not be as useful as letting the end-user choose
> what magic methods to mock, but it does solve my problem directly :)
>
I had bug reports previously that mock objects *did* work as context
managers (when they shouldn't) - which is why I don't mock magic methods
any more.
I should be able to get a fix in 0.6 though.
Michael
> $ svn diff
> Index: mock.py
> ===================================================================
> --- mock.py (revision 75)
> +++ mock.py (working copy)
> @@ -48,6 +48,11 @@
> ClassType = type(OldStyleClass)
>
> def _is_magic(name):
> +
> + # Hack because I need to use a mocked context manager.
> + if name in ('__enter__', '__exit'):
> + return False
> +
> return '__%s__' % name[2:-2] == name
>
> def _copy(value):
>
>
>
>
> On Mon, Jul 13, 2009 at 7:11 AM, Michael Foord<fuzzyman at voidspace.org.uk> wrote:
>
>> Hello Matthew,
>>
>> Technically this is a bug in Python (which will be fixed in 2.7 / 3.2) where
>> __enter__ / __exit__ are looked up on the instance rather than the class.
>>
>> That doesn't help you however. :-)
>>
>> Not sure why this works in 0.4 and fails in 0.5 - it shouldn't have worked
>> in 0.4 either. Mocking magic methods (awesome alliteration) is a tricky one
>> as it will need custom support in Mock. In general I don't think the magic
>> methods should exist on mock objects unless the programmer has configured
>> them, so I need a simple way for the user of mock to specify which magic
>> methods should exist.
>>
>> Mock is due for an update so I will think about this. I'll work out a
>> suggested API for your feedback. I guess you want __enter__ to return a mock
>> object that you can track and __exit__ to record calls to and return a
>> boolean.
>>
>> All the best,
>>
>> Michael
>>
>> Matthew Wilson wrote:
>>
>>> This test passes when I use mock 0.4 and fails with 0.5:
>>>
>>> @patch('__builtin__.open')
>>> def test_to_html(o):
>>>
>>> global b
>>> b.to_html('bogus filepath')
>>>
>>> Here's the definition of b.to_html:
>>>
>>> def to_html(self, filepath):
>>> """
>>> Write this bag out as HTML to a file at filepath.
>>> """
>>>
>>> with open(filepath, 'w') as f:
>>> f.write(self.html)
>>>
>>> mock 0.5 has this code:
>>>
>>> 128 def __getattr__(self, name):
>>> 129 if self._methods is not None:
>>> 130 if name not in self._methods:
>>> 131 raise AttributeError("Mock object has no
>>> attribute '%s'" % name)
>>> 132 elif _is_magic(name):
>>> --> 133 raise AttributeError(name)
>>>
>>> When __exit__ gets called, that code raises the AttributError.
>>>
>>> I can see good reasons fo not mocking magic methods automatically, but
>>> can I explicitly say I do want __open__ and __exit__ to be mocked?
>>>
>>> mock is great software by the way.
>>>
>>> Matt
>>>
>>>
>>>
>>>
>> --
>> http://www.ironpythoninaction.com/
>> http://www.voidspace.org.uk/blog
>>
>>
>>
>>
>
>
>
>
--
http://www.ironpythoninaction.com/
http://www.voidspace.org.uk/blog
More information about the testing-in-python
mailing list