Reputation: 3288
Can't provide much context given the complexity, but I'm hoping for some insight/thought-provoking questions as to why this is happening.
I'm testing a process which loads files into a database, so I'm patching the credentials for a database connection using unittest.mock.patch
to use test and not production credentials. We have a series of mocks that are applied as a contextmanager
, simplified version here:
from contextlib import ExitStack
def context_stack(contexts):
stack = ExitStack()
for context in contexts:
stack.enter_context(context)
return stack
def patch_mocks():
mocks = [
patch('db_config.ReadWrite', db_mocks.ReadWrite),
patch('db_config.ReadWrite', db_mocks.ReadWrite)
]
return context_stack(mocks)
It gets used as such (simplified):
with patch_mocks():
LoadFiles(file_list)
LoadFiles
will iterate over each file in file_list
and attempt to insert the contents into the database. The underlying methods connect to the database using db_config.ReadWrite
but of course they are patched by db_mocks.ReadWrite
. This works pretty consistently except, seemingly very randomly, it will fail as it tries to instead use db_config.ReadWrite
when trying to create the connection.
So for example, there could be a hundred files, and it will patch the most of them successfully, but it will randomly stop using the patch halfway through and fail the test. What conditions/variables could be causing this patch to not be applied? Is there a limit to the number of patches that can be applied? Should it be applied in another way?
Upvotes: 2
Views: 465
Reputation: 2418
Do not patch/mock, instead use the repository pattern to access the database.
You would then have two implementations of the Repository interface:
Upvotes: 0
Reputation: 1794
My first line of investigation would involve this warning from the docs on .patch():
target should be a string in the form 'package.module.ClassName'. The target is imported and the specified object replaced with the new object, so the target must be importable from the environment you are calling patch() from. The target is imported when the decorated function is executed, not at decoration time.
and this further explanation on Where to patch
The basic principle is that you patch where an object is looked up, which is not necessarily the same place as where it is defined.
I would try to find a broken case and check the status of the import environment there to make sure the same import you're using everywhere else is reachable from there.
Upvotes: 1