Mocking before importing a module
How can I patch and mock getLogger
in this module under test (MUT):
# Start of the module under test
import logging
log = logging.getLogger('some_logger')
# ...
I would like to do:
mock_logging.getLogger.return_value = Mock()
However I can't create mock_logging
before importing the MUT, but importing the MUT already calls get开发者_JS百科Logger
...
This can be done by first importing and patching logging.getLogger
and only then import your mut
import unittest
from unittest import mock
import logging
with mock.patch('logging.getLogger') as mock_method:
import mut
mock_method.assert_called_once_with('some_logger')
Alternatively, useful when patching more than one method:
import unittest
from unittest import mock
import logging
mock_method = mock.patch('logging.getLogger').start()
import mut
mock_method.stop()
mock_method.assert_called_once_with('some_logger')
This would require importing the module without executing it first, which unfortunately for you won't work unless you do some fancy hacks like modifying the parse tree for the module, but you probably don't want to do that either.
What you could do is to modify these import-time reference after the import and replace them manually by mock-objects or reexecute the statements after your mock-object is install, though I know, that this is of limited use.
You need to import the module inside a mocked context and remove the module from sys.modules
after importing so the mock doesn't persist in other tests that import mut
:
import sys
from unittest import mock
with mock.patch("logging.getLogger") as mock_logging:
import mut
del sys.modules["mut"]
...
Alternatively with pytest:
import sys
import pytest
def mock_get_logger(name):
print("mock logger name", name)
with pytest.MonkeyPatch().context() as ctx:
ctx.setattr("", mock_get_logger)
from main import app
del sys.modules["main"]
...
精彩评论