0

I feel bad for asking such a simple question but I'm really confused as to why this example does not work as expected. I expect that the following assert would fail with a value of 70 but the test passes with a value of 30.

The following is in a pip package called calc:

calc/__init__.py
from .calculator import *
calc/calculator.py
def get_value_1():
 return 10
def get_value_2():
 return 20
def addition():
 return get_value_1() + get_value_2()
test/simple.test
import calc
@mock.patch('calc.get_value_1', return_value=50)
def test1(mock_data):
 value = calc.addition()
 assert value == 30
Test output:
plugins: cov-2.6.0, nbval-0.9.1
collected 1 item 
test/simple_test.py::test6 PASSED
================= 1 passed in 0.21 seconds ===================
asked Dec 13, 2018 at 22:58
6
  • The addition function returns get_value_1() + get_value_2() which is equivalent to 10 + 20 = 30. So if you call the addition function, you should get 30. Though you patched calc.get_value_1, by the time you have loaded calc, it already has been defined so that it returns 30. Commented Dec 13, 2018 at 23:04
  • Yes, but I change the return value of what the get_value_1 should be. So, instead of returning 10, it now returns 50, which would cause the return value of 70 instead of 30. Commented Dec 13, 2018 at 23:08
  • Updated comment Commented Dec 13, 2018 at 23:09
  • I dont know, patch should just replace the object with the patched object, see docs.python.org/3/library/unittest.mock.html#patch - OP I think the culprit is the namespace you are patching Commented Dec 13, 2018 at 23:17
  • 1
    As a guess, you're patching calc.get_value_1 when you should be patching calc.calc.get_value_1. It's impossible to tell for sure, though, since what you've posted displays indicators that it doesn't quite match anything you actually ran. Commented Dec 13, 2018 at 23:27

2 Answers 2

2

The answer of @JulienChein is pretty good, and I will just add some example based on you snippet.

I create a similar environment to your.

.
├── calculator.py
├── __init__.py
└── test
 ├── __init__.py
 └── test_calc.py

calculator.py

def get_value_1():
 return 10
def get_value_2():
 return 20
def addition():
 return get_value_1() + get_value_2()

__init__.py

from .calculator import *

test/test_calc.py

from unittest.mock import patch
from .. import addition
# Here get_value_1, is mocked from calc.__inti__.py
@patch('calc.get_value_1', return_value=50)
def test1(mock_data):
 value = addition()
 assert value == 30 # This assert is False
# Here get_value_1, is mocked from calc.calculator.py
@patch('calc.calculator.get_value_1', return_value=50)
def test2(mock_data):
 value = addition()
 assert value == 70 # This assert is True

The point is that addition uses methods from calc.calculator.py, that's why you need to mock the method from this file.

answered Dec 14, 2018 at 10:42
Sign up to request clarification or add additional context in comments.

1 Comment

thank you so much for your response, I understand what I did wrong. I got my higher level examples working now!
2

Make sure you are patching the correct target. Specifically, follow the 'Where to Patch' section here: https://docs.python.org/3/library/unittest.mock.html#id5

From your posted files, it seems possible that some names are mixed up ('calc' or 'calculator', for example). Make sure to read through the docs, especially:

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.

Patching, if you are just starting to do it, can be pretty confusing / maddening. Maybe add an import pdb; pdb.set_trace() (debugger) in the test. This would pause the test at this statement. You can then check what get_value_1 gives you. If it's of type MagicMock or some such, then the patch succeeded. If it's not, then you failed to patch the correct thing and should change the target path. Hope this helps!

Also: are you sure @mock.patch('calc.get_value_1', return_value=50) would work? I would try mock.patch('calc.get_value_1') then add mock_data.return_value = 50 inside the test function. I haven't seen your way before and a brief digging of the source code didn't show me it would work (didn't show me it wouldn't work either!) - worth trying.

answered Dec 13, 2018 at 23:24

1 Comment

Your right about the snippets that I put in, I the calc.py file is suppose to be calculator.py but that was just a mistype and what was not actually in the code. As for not patching the correct thing, there is not to many other things to really patch in this example, but I will give the pdb.set_trace() a try. Thanks for the help.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.