AaronV77
AaronV77

Reputation: 119

Mock a python function that is used by another function

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

Answers (2)

Mauro Baraldi
Mauro Baraldi

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

Julien Chien
Julien Chien

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

Related Questions