ca9163d9
ca9163d9

Reputation: 29229

mock.patch not working in pytest fixture?

I need to write test case for f2() in the following mod1.

mod1.py:

from mod_x import X

def f1():
    raise Exception('Test shouldn''t call real f1()')

def f2():
    f1()

And the following is the imported mod_x.

mod_x.py

class Y:
    def func2(self):
        raise Exception("Shouldn't be called")

class X:
    def __init__(self):
        self.producer = Y()

Here is the test code test_mod1.py. It suppose to patch mod1.f1 so the real f1() shouldn't be called.

import mod1
import pytest
from unittest import mock

@pytest.fixture()
@mock.patch('mod1.f1')
def patched_mocked(mocked_function):
    x_mock = mock.Mock(mod1.X)
    x_mock.producer = mock.Mock()
    x_mock.producer.func2 = lambda : None
    mocked_function.return_value = x_mock
    return x_mock   

def test_1(patched_mocked):
    mod1.f2() # f2() shouldn't call the real f1() because of patching
    # assert ....

def test_2(patched_mocked):
    mod1.f2()
    # assert ....

However,

test_mod1.py FF                                                                                                                                                                                                      [100%]

======================================================================================================== FAILURES ========================================================================================================= 
_________________________________________________________________________________________________________ test_1 __________________________________________________________________________________________________________ 

patched_mocked_function = 

    def test_1(patched_mocked_function):
>       mod1.f2()

test_mod1.py:15:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
mod1.py:7: in f2
    f1()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    def f1():
>       raise Exception('Test shouldn''t call real f1()')
E       Exception: Test shouldnt call real f1()

mod1.py:4: Exception

Upvotes: 3

Views: 4231

Answers (1)

MrBean Bremen
MrBean Bremen

Reputation: 16855

You cannot use the patch decorator on a fixture, because the mock will be reverted at the time you return the fixture. You need to make sure that the mock is reverted (e.g. goes out of scope) only after the test ends (e.g. after the fixture lifetime):

@pytest.fixture()
def patched_mocked():
    with mock.patch('mod1.f1') as mocked_function:
        x_mock = mock.Mock(mod1.X)
        x_mock.producer = mock.Mock()
        x_mock.producer.func2 = lambda: None
        mocked_function.return_value = x_mock
        yield x_mock

In this case the mock is reverted only after the yield returns, which is after the test has finished.

Upvotes: 9

Related Questions