How to avoid pytest mocked data conflicting between tests

I have two commands (django management commands) which load data from an API, then do something based on the data they collect. So certain function names are the same for consistency, like get_api_data to gather data and get_specific_event to get an event from the data.

In the test module for each command I have a function that returns a dictionary to represent the data from the API which the command expects. For example;

#test_command_one.py

from core.management.commands.command_one import Command as CommandOne

def get_data(current_event=None, next_event=1):
    return {
        "current": current_event,
        "next": next_event,
        "data": [
            {
                "id": i,
                "time": time,
            }
            for i, time in enumerate(
                [
                    "2023-08-11 17:30:00+00:00",
                    "2023-08-18 17:15:00+00:00",
                    "2023-08-25 17:30:00+00:00",
                    "2023-09-01 17:30:00+00:00",
                    "2023-09-16 10:00:00+00:00",
                ],
                start=1,
            )
        ],
    }


@pytest.mark.django_db
class TestCommandOne:

    def test_get_current_event(self, mocker):
        cmd = CommandOne()
        m_events = mocker.patch.object(cmd, "get_api_data")

        m_events.return_value = get_data(next_event=1)
        assert cmd.get_current_event() is None
#test_command_two.py

from project.management.commands.command_two import Command

def get_events():
    return {
        "data": [
            {
                "id": i,
                "time": time,
                "time2": time,
                "time3": time,
            }
            for i, time in enumerate(
                [
                    "2023-08-11 17:30:00+00:00",
                    "2023-08-18 17:15:00+00:00",
                    "2023-08-25 17:30:00+00:00",
                    "2023-09-01 17:30:00+00:00",
                    "2023-09-16 10:00:00+00:00",
                ],
                start=1,
            )
        ],
    }


def test_valid_output(mocker):
    mocker.patch.object(
        Command, "get_api_data", return_value=get_events()
    )
    out2 = StringIO()
    call_command("command_two", stdout=out2)

Running the tests in isolation they pass. But when running the whole test suite, I’m seeing;

FAILED project/tests/test_command_two.py::test_valid_output - KeyError: 'time2'

So the data being used by the second test is still the return value of m_events = mocker.patch.object(cmd, "get_api_data") in the first test.

How do I either clear these mocks at the beginning of a test, or ensure that the new mock is used?

I’d expect that each time you define mocker.patch.object(cmd, "get_api_data") for a test, it’s specified return value is the one used for the context of that test.

Leave a Comment