2

Trying to understand unittest.mock more, but not sure why its running the program twice. For simplicity, consider the code below in a file test.py:

from unittest.mock import patch

class T():
    def __init__(self):
        self.setup()

    def setup(self):
        mock_testing = patch('test.testing').start()
        mock_testing.return_value = "new testing"

def testing():
    return "testing"

print("Hello")

t = T()

print("Setting up")

if testing() == "testing":
    print("old style")
elif testing() == "new testing":
    print("new style")

When I run the script with python test.py, I get:

Hello
Hello
Setting up
new style
Setting up
old style

Why does it run the code twice? And even if it does run it twice, how come 'hello' is printed back to back, should it be printed like:

Hello
Setting up
new style
Hello
Setting up
old style

Also how can I make it so that it just runs the code once, with the mock value of 'new testing'?

1
  • I am running it as python test.py.. and it does give those results Commented Nov 14, 2019 at 0:34

1 Answer 1

3

This is because the script is loaded as the module __main__ first, and yet you're calling patch with test.testing, so patch will import test.py again as the test module. Since patch is called before "Setting up" is printed, the loading of the test module, as well as the printing of "Hello" by both the __main__ module and the test module, will be done before "Setting up" is printed by the __main__ module.

If you add __name__ to the arguments for print, you'll more easily see what's going on:

from unittest.mock import patch

class T():
    def __init__(self):
        self.setup()

    def setup(self):
        mock_testing = patch('test.testing').start()
        mock_testing.return_value = "new testing"

def testing():
    return "testing"

print(__name__, "Hello")

t = T()

print(__name__, "Setting up")

if testing() == "testing":
    print(__name__, "old style")
elif testing() == "new testing":
    print(__name__, "new style")

This outputs:

__main__ Hello
test Hello
test Setting up
test new style
__main__ Setting up
__main__ old style

To avoid this, you should patch __main__.testing instead, so that after the modification, the above code will output:

__main__ Hello
__main__ Setting up
__main__ new style
Sign up to request clarification or add additional context in comments.

2 Comments

That makes a lot of sense. Didnt realize patch was importing the module again. Thanks a lot for the explanation!
Importing the same module with two different names is strongly discourage and can lead to loads of weird errors. In fact code is imported twice, global variables exist in two different name spaces with potentially two different values. patch imports the module only again if you import it with a different name. In other words if you execute a script as __main__, then you should not patch "test.testing" you should have mocked "__main__.testing" instead.

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.