0

I have the below pytest script and the side_effect value [2, 6] is not getting iterated. It is always stuck with value 2 in the test function test_my_function.

My question is:

How to make the side_effect value iterate together with parametrize test cases in function test_my_function. (assume we must use parametrize).

#!/usr/bin/env python3
#

import pytest

def my_function(x):
    return x*2

@pytest.fixture
def mock_my_function(mocker):
    mocker.patch(
        __name__ + ".my_function", side_effect=[2, 6]
    )

@pytest.mark.parametrize("input, expect", [(1, 2), (3, 6)])
def test_my_function(input, expect, mock_my_function):
    assert expect == my_function(input)

    
Xianlin
  • 1,139
  • 5
  • 20
  • 34
  • I'm not sure what you want to achieve with `side_effect` here. If you would call `my_function` a second time in the same test, it would get the second value of `side_effect`, but then your expected value would not match. Can you explain what are you trying to do? – MrBean Bremen Aug 01 '21 at 08:22
  • Sorry the above is just to illustrate `mocker.patch` does not iterate together with `parametrize` and my purpose is to have `mocker.patch` iterate together with `parametrize` set of values. The below answer enlightened me and it is the solution. Thank you – Xianlin Aug 02 '21 at 14:55

1 Answers1

1

first, your test isn't really testing anything if you mock the function you're trying to test

second, function-scoped fixtures are set up each time the test function is called -- for each parametrization case-set it'll run your fixture

this means (in your example) that both invocations of your test will have my_function mocked to return 2 for the only call that happens

if you want to additionally parametrize the mocked function, I would suggest including it in your parametrize list:

@pytest.mark.parametrize(
    ('input', 'expect', 'mocked_ret'),
    (
        (1, 2, 2),
        (3, 6, 6),
    ),
)
def test_my_function(input, expect, mocked_ret, mocker):
    mocker.patch(f"{__name__}.my_function", return_value=mocked_ret)

    assert my_function(input) == expect

disclaimer: I'm a pytest core dev

anthony sottile
  • 61,815
  • 15
  • 148
  • 207
  • sorry for my bad example as the above, my purpose is to have a mocked API return response set goes together with `input` and `expect`. you have provided a simple solution and I didn't know I can include 3 items in one tuple. Thank you. – Xianlin Aug 02 '21 at 14:53