Skip to content
Advertisement

How to patch a constant in Python using a mock as function parameter

I’m trying to understand the different ways to patch a constant in Python using mock.patch. My goal is to be able to use a variable defined in my Test class as the patching value for my constant.

I’ve found this question which explains how to patch a constant: How to patch a constant in python And this question which explains how to use self in patch: using self in python @patch decorator

But from this 2nd link, I cannot get the testTwo way (providing the mock as a function parameter) to work

Here is my simplified use case:

mymodule.py

JavaScript

test_mymodule.py

JavaScript

My guess is I shoudln’t use return_value, because mock_MY_CONSTANT is not a function. So what attribute am I supposed to use to replace the value returned when the constant is called ?

Advertisement

Answer

I think you’re trying to learn about unit tests, mock objects, and how to replace the value of a constant in the code under test.

I’ll start with your specific question about patching a constant, and then I’ll describe a more general approach to replacing constant values.

Your specific question was about the difference between patch("mymodule.MY_CONSTANT", 3) and patch("mymodule.MY_CONSTANT"). According to the docs, the second parameter is new, and it contains the replacement value that will be patched in. If you leave it as the default, then a MagicMock object will be patched in. As you pointed out in your question, MagicMock.return_value works well for functions, but you’re not calling MY_CONSTANT, so the return value never gets used.

My short answer to this question is, “Don’t use MagicMock to replace a constant.” If for some reason, you desperately wanted to, you could override the only thing you are calling on that constant, its __eq__() method. (I can’t think of any scenario where this is a good idea.)

JavaScript

Now for the more general question. I think the simplest approach is not to change the constant, but to provide a way to override the constant. Changing the constant just feels wrong to me, because it’s called a constant. (Of course that’s only a convention, because Python doesn’t enforce constant values.)

Here’s how I would handle what you’re trying to do.

JavaScript

Then your regular code can just call get_constant(), and your test code can provide an override.

JavaScript

This can become more painful as your code gets more complicated. If you have to pass that override through a bunch of layers, then it might not be worth it. However, maybe that’s showing you a problem with your design that’s making the code harder to test.

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement