25

I am new to mock and unit testing in python. How can I mock the local variable of a function? For example, how do I change age to 10 instead of 27 while testing?

# data_source.py
def get_name():
    age = 27 #real value
    return "Alice"

# person.py
from data_source import get_name

class Person(object):
    def name(self):
        return get_name()

# The unit test 
from mock import patch
from person import Person
   
@patch('person.age')
def test_name(mock_age):
    mock_age = 10 # mock value
    person = Person()
    name = person.name()
    assert age == 10
2
  • stackoverflow.com/questions/50253429/… might help Commented Jan 8, 2021 at 7:02
  • If changing the age value from outside is required in order to test the function, then setting that value should not be a part of the function's work. Here, the test system is automatically warning you about a major code-design issue, simply by existing. Commented Mar 26, 2021 at 5:09

3 Answers 3

6

As far as I know, mock cannot mock a local variable. It can only mock non-local object.

Trying to mock a local variable sounds dubious. Maybe you should try another way. Try making age a global variable or a class variable. Then you can use mock to mock the global variable or the class variable.

Such as:

# source file
G_AGE = 27

def get_name():
    return "Alice"

# unit test file
...
@patch('XXX.G_AGE')
def test_name(mock_age):
    mock_age = 10
    ....

Just pay attention to patch usage: mock may not work as expected if it is not used properly. Refer to Where to patch for further explanation.

Sign up to request clarification or add additional context in comments.

Comments

1

I can't imagine why you would want to do this. Testing is for checking your actual functions work the way they are written, not changing the way they work so they match an arbitrary test.

In any case, I suspect you want to pass a parameter with a default value:

def get_values(age=27, name="Alice")
    ...

4 Comments

You say that, but that is exactly why mock was written: to change the way your function works so that it is easier/faster to test. For example, I have inherited a lot of published API code that interacts with some very slow IO. I would love to be able to override the timeout variable (local and constant within my function-under-test) so that I could test the exception behavior without having to wait for real-world (5-7 minute) timeout scenarios.
You might need to mock success/fail on a variable returned from a remote process or API call.
@anregen "Change the way your function works" by modifying its environment, not by modifying its own implementation. The fact that you want the timeout value to be modifiable from outside highlights that it is a dependency which should be injected. If you're supposed to be testing the code in question, you should be allowed to fix it. If not, then you're testing client code that uses the thing doing the IO, and you should mock that entire thing, not just its timeout value. Even beyond code organization, you don't want your test to depend on the IO succeeding!
@nmcilree you do that by mocking the process/call itself, such that the mock returns success/fail as appropriate.
0

StackOverflow deletes duplicate answers even on a different question, so go there for my answer to this question.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.