Question

Using mock in python, top level packages (like argparse) cannot be patched outright - presumably because there is no reference to patch. One solution is to patch every individual call into the package (like argparse.ArgumentParser). In theory, if calls to the package were added without a corresponding patch that would result in an accidental call to an import during a unit test.

Although the workaround is not all that inconvenient, it would be ideal to patch packages like argparse outright. mock_open appears to employ some shenanigans to patch the built in open() using __main__.open. How does that work, and could similar shenanigans be used to patch top level packages?

Was it helpful?

Solution

import unittest.mock as mock

mock_argparse = mock.Mock()
with mock.patch.dict('sys.modules', argparse=mock_argparse):
    import argparse
    print(argparse.ArgumentParser()) 
# <Mock name='mock.ArgumentParser()' id='140681471282448'>

As for mock_open patching:

m = mock_open()
with patch('__main__.open', m, create=True):

It seems like it creates __main__.open attribute with mock object which shadows the built-in version as if you defined open() function in your module. I suppose for the actual tests you should patch module_x.open() where "module_x" is the module that actually calls open().

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top