Skip to content

assert_called_once_with calls __eq__ multiple times #353

@akotrei

Description

@akotrei

I have the next snippet of code:

import pytest
import pandas as pd


class Class:
    def __init__(self, df) -> None:
        self.df = df

def f(df): Class(df)

@pytest.fixture
def mocked_class_init(mocker):
    return mocker.patch.object(Class, '__init__', return_value=None)

def cmp_df(x, y, l=[0]):
    print(f'invocked {l[0]} times')
    l[0] += 1
    return x.df.equals(y)

def test(mocker, mocked_class_init):
    df_actual = pd.DataFrame(data={'v': [1, 2, 3]})
    df_expected = pd.DataFrame(data={'v': [1, 3, 3]})
    f(df_expected)

    df_mocked = mocker.Mock()
    df_mocked.df = df_actual
    df_mocked.__eq__ = lambda x, y: cmp_df(x, y)
    mocked_class_init.assert_called_once_with(df_mocked)

and getting the next result:

===================================================================== test session starts =====================================================================
platform linux -- Python 3.8.10, pytest-7.2.1, pluggy-1.0.0
rootdir: /home/andrei/projects/jinja
plugins: mock-3.10.0
collected 1 item                                                                                                                                              

test.py F                                                                                                                                               [100%]

========================================================================== FAILURES ===========================================================================
____________________________________________________________________________ test _____________________________________________________________________________

__wrapped_mock_method__ = <function NonCallableMock.assert_called_with at 0x7f7b5e698dc0>
args = (<MagicMock name='__init__' id='140167289940672'>, <Mock id='140167290096752'>), kwargs = {}, __tracebackhide__ = True
msg = "expected call not found.\nExpected: __init__(<Mock id='140167290096752'>)\nActual: __init__(   v\n0  1\n1  3\n2  3)"
__mock_self = <MagicMock name='__init__' id='140167289940672'>, actual_args = (   v
0  1
1  3
2  3,), actual_kwargs = {}, introspection = ''
@py_assert2 = (<Mock id='140167290096752'>,)

    def assert_wrapper(
        __wrapped_mock_method__: Callable[..., Any], *args: Any, **kwargs: Any
    ) -> None:
        __tracebackhide__ = True
        try:
>           __wrapped_mock_method__(*args, **kwargs)

env/lib/python3.8/site-packages/pytest_mock/plugin.py:444: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <MagicMock name='__init__' id='140167289940672'>, args = (<Mock id='140167290096752'>,), kwargs = {}, expected = ((<Mock id='140167290096752'>,), {})
actual = call(   v
0  1
1  3
2  3), _error_message = <function NonCallableMock.assert_called_with.<locals>._error_message at 0x7f7b3d89e0d0>, cause = None

    def assert_called_with(self, /, *args, **kwargs):
        """assert that the last call was made with the specified arguments.
    
        Raises an AssertionError if the args and keyword args passed in are
        different to the last call to the mock."""
        if self.call_args is None:
            expected = self._format_mock_call_signature(args, kwargs)
            actual = 'not called.'
            error_message = ('expected call not found.\nExpected: %s\nActual: %s'
                    % (expected, actual))
            raise AssertionError(error_message)
    
        def _error_message():
            msg = self._format_mock_failure_message(args, kwargs)
            return msg
        expected = self._call_matcher((args, kwargs))
        actual = self._call_matcher(self.call_args)
        if expected != actual:
            cause = expected if isinstance(expected, Exception) else None
>           raise AssertionError(_error_message()) from cause
E           AssertionError: expected call not found.
E           Expected: __init__(<Mock id='140167290096752'>)
E           Actual: __init__(   v
E           0  1
E           1  3
E           2  3)

/usr/lib/python3.8/unittest/mock.py:913: AssertionError

During handling of the above exception, another exception occurred:

mocker = <pytest_mock.plugin.MockerFixture object at 0x7f7b3d86a730>, mocked_class_init = <MagicMock name='__init__' id='140167289940672'>

    def test(mocker, mocked_class_init):
        df_actual = pd.DataFrame(data={'v': [1, 2, 3]})
        df_expected = pd.DataFrame(data={'v': [1, 3, 3]})
        f(df_expected)
    
        df_mocked = mocker.Mock()
        df_mocked.df = df_actual
        df_mocked.__eq__ = lambda x, y: cmp_df(x, y)
>       mocked_class_init.assert_called_once_with(df_mocked)

test.py:27: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/lib/python3.8/unittest/mock.py:925: in assert_called_once_with
    return self.assert_called_with(*args, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self =        v
0  False
1  False
2  False

    @final
    def __nonzero__(self) -> NoReturn:
>       raise ValueError(
            f"The truth value of a {type(self).__name__} is ambiguous. "
            "Use a.empty, a.bool(), a.item(), a.any() or a.all()."
        )
E       ValueError: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

env/lib/python3.8/site-packages/pandas/core/generic.py:1466: ValueError
-------------------------------------------------------------------- Captured stdout call ---------------------------------------------------------------------
**invocked 0 times
invocked 1 times
invocked 2 times
invocked 3 times**
=================================================================== short test summary info ===================================================================
FAILED test.py::test - ValueError: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
====================================================================== 1 failed in 0.39s ======================================================================

Could somobody explans me why cmp_df function is being invoked multiple times when I'm trying to test that function f called with a proper pandas dataframe? May be I use a wrong way to test that scenario?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions