Reputation: 119
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 ===================
Upvotes: 0
Views: 1247
Reputation: 6575
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.
Upvotes: 2
Reputation: 2190
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.
Upvotes: 2