[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