Home > Net >  Why isn't my mock.assert_called_once() passing?
Why isn't my mock.assert_called_once() passing?

Time:07-28

I have function 1 here:

def f1(x):
    f2(x 3)
    return x * x

And function 2 here:

def f2(y):
    print("Whatever you do, don't print this.")

I wrote my test here:

def test_f1(mocker):
    mock = mocker.patch("functions.f2")
    assert f1(1) == 1
    assert f2(1) is None
    mock.f2.assert_called_once()

When I run pytest, it throws the error:

>       mock.f2.assert_called_once()
E       AssertionError: Expected 'f2' to have been called once. Called 0 times.

I literally just called "f2" but it's not picking up on it? Not sure why.

CodePudding user response:

For a number of reasons:

  1. mocker.patch returns the mock, so the mocked f2 is mock, not mock.f2.

  2. From the code you posted, it appears you have a line like

    from functions import f1, f2
    

    or

    from functions import *
    

    This means that if you monkey-patch functions.f2, you are not monkey-patching your local variable f2. mock is the same as the mocked functions.f2, but f2 is no longer the same as functions.f2 (because it's the original functions.f2, not the mocked one). You can fix this (along with problem #1) with code like:

    f2 = mocker.patch("functions.f2")
    # ...
    f2.assert_called_once()
    
  3. Except now assert f2(1) is None will fail. This is because you mocked f2. That means the real f2 isn't called. Did you mean to do a spy instead of a mock? With a spy, the real function is called. pytest-mock can handle spies, though you might need to change your imports slightly:

    import functions
    from functions import f1, f2
    
    def test_f2(mocker):
        f2 = mocker.spy(functions, 'f2')
        assert f1(1) == 1
        assert f2(1) is None
        f2.assert_called_once()
    
  4. And now we finally...get a failed assert_called_once() again, this time because f2 has been called twice. That's because it's called once when you call f1(1), and then a second time when you call f2(1).

CodePudding user response:

You're asserting that mock.f2() was done, not that f2() was done.

I'm not exactly clear on what kind of object your fixture mocker is, nor am I sure I understand what you actually want to do, but perhaps you want mock.assert_called_once()? You can also check mock.mock_calls().

  • Related