jsatt / mock

Automatically exported from code.google.com/p/mock
BSD 2-Clause "Simplified" License
0 stars 0 forks source link

mock_open documentation: patch __builtin__ instead of __main__? #204

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
In the examples for using mock_open, wouldn't it be better to patch 
'__builtin__.open'?  I was a bit confused when it stopped working with 
nosetests.

AttributeError: <module '__main__' from 
'/secret-lair/python-ve/permanent/bin/nosetests'> does not have the attribute 
'open'

Original issue reported on code.google.com by dirk.imp...@gmail.com on 9 May 2013 at 1:44

GoogleCodeExporter commented 8 years ago
Patching __builtin__ is an antipattern as you're then patching globally for all 
callers. Patching in the namespace you're using is much better practise. In the 
documentation that namespace is __main__.

Patching a builtin like open requires passing the "create=True" flag to patch. 
This can be surprising, as you've discovered. We may fix this particular issue 
by relaxing the restriction on patching builtins - so you don't need to pass 
the "create=True" flag.

Original comment by fuzzyman on 9 May 2013 at 10:31

GoogleCodeExporter commented 8 years ago
Sorry, threw in the wrong error message.  Thought that was an easy one but that
makes sense.  Maybe this is a nose problem but I have a test with exactly the
example code failing under nose only if I use '__main__'.  Here the full code.
Any thoughts?  It's in a virtualenv and 

Python-2.7
mock==1.0.1
nose==1.3.0

-----------

#!/usr/bin/env python

from mock import *
import unittest

class TestA(unittest.TestCase):

    def test_open_mock_like_example_read(self):

        with patch('__main__.open', mock_open(read_data='bibble'), create=True) as m:
            with open('foo') as h:
                assert m is open
                result = h.read()
        m.assert_called_once_with('foo')
        assert result == 'bibble'

if __name__ == '__main__':
    unittest.main()

----------

This is the error message:

E
======================================================================
ERROR: test_open_mock_like_example_read (noseprobs_tests.TestA)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "...", line 16, in test_open_mock_like_example_read
    with open('foo') as h:
IOError: [Errno 2] No such file or directory: 'foo'

----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (errors=1)

Original comment by dirk.imp...@gmail.com on 10 May 2013 at 6:50

GoogleCodeExporter commented 8 years ago
It works when executed directly:

(permanent)dirk@nutts ~/test-examples $ python mocking_tests.py
.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK
(permanent)dirk@nutts ~/test-examples $ nosetests mocking_tests.py 
E
======================================================================
ERROR: test_open_mock_like_example_read (mocking_tests.TestA)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/dirk/test-examples/mocking_tests.py", line 11, in test_open_mock_like_example_read
    with open('foo') as h:
IOError: [Errno 2] No such file or directory: 'foo'

----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (errors=1)

Original comment by dirk.imp...@gmail.com on 10 May 2013 at 7:28

Attachments:

GoogleCodeExporter commented 8 years ago
Right, that's because when you execute it directly the current namespace is 
called "__main__" (which is where you have done your patching). When you 
execute it through nosetest the test module is imported and has a different 
name. You can find the *actual* name of the current namespace using __name__. 
So instead of patching "__main__.open" you could use "%s.open" % __name__

Original comment by fuzzyman on 10 May 2013 at 9:22

GoogleCodeExporter commented 8 years ago
Oh, man. Of course. I'm kind of in between languages right now.  I should
have known that.  Sorry for bothering you.

Original comment by dirk.imp...@gmail.com on 10 May 2013 at 6:29