Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pytest with mock/pytest-mock

For some reason I cannot get mock.patch to work in any scenario when using Pytest. It simply doesn't do the patching. Am I using it incorrectly or is something messed up with my configuration?

base.py

def foo():
    return 'foo'

def get_foo():
    return foo()

test_base.py

import pytest
import mock
from pytest_mock import mocker

from base import get_foo

@mock.patch('base.foo') 
def test_get_foo(mock_foo):
    mock_foo.return_value = 'bar'
    assert get_foo() == 'bar'

def test_get_foo2(mocker):
    m = mocker.patch('base.foo', return_value='bar')
    assert get_foo() == 'bar'

def test_get_foo3():
    with mock.patch('base.foo', return_value='bar') as mock_foo:
        assert get_foo() == 'bar'

pytest results

============================================================= test session starts =============================================================
platform linux2 -- Python 2.7.13, pytest-3.0.7, py-1.4.33, pluggy-0.4.0
rootdir: /projects/git/ABC/query, inifile:
plugins: mock-1.6.0
collected 13 items 

test_base.py .....FFF.....

================================================================== FAILURES ===================================================================
________________________________________________________________ test_get_foo _________________________________________________________________

mock_foo = <MagicMock name='foo' id='140418877133648'>

    @mock.patch('base.foo')
    def test_get_foo(mock_foo):
        mock_foo.return_value = 'bar'
>       assert get_foo() == 'bar'
E       AssertionError: assert 'foo' == 'bar'
E         - foo
E         + bar

test_base.py:67: AssertionError
________________________________________________________________ test_get_foo2 ________________________________________________________________

mocker = <pytest_mock.MockFixture object at 0x7fb5d14bc210>

    def test_get_foo2(mocker):
        m = mocker.patch('base.foo', return_value='bar')
>       assert get_foo() == 'bar'
E       AssertionError: assert 'foo' == 'bar'
E         - foo
E         + bar

test_base.py:71: AssertionError
________________________________________________________________ test_get_foo3 ________________________________________________________________

    def test_get_foo3():
        with mock.patch('base.foo', return_value='bar') as mock_foo:
>           assert get_foo() == 'bar'
E           AssertionError: assert 'foo' == 'bar'
E             - foo
E             + bar

test_base.py:75: AssertionError
like image 751
ZakJ Avatar asked May 24 '17 18:05

ZakJ


People also ask

Can you use mock with pytest?

In pytest , mocking can replace the return value of a function within a function. This is useful for testing the desired function and replacing the return value of a nested function within that desired function we are testing.

What is mock pytest?

New in version 3.3. unittest.mock is a library for testing in Python. It allows you to replace parts of your system under test with mock objects and make assertions about how they have been used.

What does mocker patch do?

patch() unittest. mock provides a powerful mechanism for mocking objects, called patch() , which looks up an object in a given module and replaces that object with a Mock . Usually, you use patch() as a decorator or a context manager to provide a scope in which you will mock the target object.

What is MagicMock?

MagicMock. MagicMock objects provide a simple mocking interface that allows you to set the return value or other behavior of the function or object creation call that you patched. This allows you to fully define the behavior of the call and avoid creating real objects, which can be onerous.


1 Answers

The problem was due to the relationship between my import specification and PATH variable. If I specified the entire path in the patch argument, like: @mock.patch('<PROJECT_ROOT>.<SUBPACKAGE>.base.foo') where PATH had the parent directory of as an entry, then it worked. I don't know why it wasn't throwing an import error if it wasn't finding base.foo. And if it wasn't finding it, I don't understand how the scope was different.

like image 56
ZakJ Avatar answered Sep 23 '22 02:09

ZakJ