[TIP] mock.patch in version 0.5 doesn't mock __exit__ method on open files

Matthew Wilson matt at tplus1.com
Mon Jul 13 07:30:58 PDT 2009


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

$ 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
>
>
>



-- 
Matthew Wilson
matt at tplus1.com
http://tplus1.com



More information about the testing-in-python mailing list