[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