Skip to content

Modifying an object passed to a mocked function corrupts call_args_list #157057

Description

@TiphaineLAURENT

Bug description:

# test.py

# src

def my_function(message: dict) -> None:
    pass

def main() -> None:
    # Consider that message is a heavier object, hence the need to update it instead of copying
    message = {"channel": "first_channel"}
    my_function(message)

    message["channel"] = "second_channel"
    my_function(message)


# tests

import unittest.mock


def test() -> None:
    with unittest.mock.patch("test.my_function") as my_function_mock:
        main()

        for call_arg, expected_channel in zip(my_function_mock.call_args_list, ["first_channel", "second_channel"]):
            assert (
                call_arg.args[0]["channel"] == expected_channel
            )  # Fails as call_arg.args[0]["channel"] is always equal to the last call to `my_function`, which is "second_channel"

Run it through pytest test.py

This is a problem as the object we mutate is a bit more heavy that just a dict with 1 field, hence the need to update it.
I would expected call_args_list to copy the call args / kwargs instead of keeping a reference to it.

The code has been tested in productions and works as expected.

CPython versions tested on:

3.13

Operating systems tested on:

Linux

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    stdlibStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or error

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions