Skip to content

ThreadingMock.call_count is not thread safe #142651

@godlygeek

Description

@godlygeek

Bug report

Bug description:

Running this test program with (plain old, non-free-threaded) Python 3.14 fails:

import threading
import unittest.mock

m = unittest.mock.ThreadingMock()

LOOPS = 10_000
THREADS = 10


def test_function():
    for _ in range(LOOPS):
        m()


threads = [threading.Thread(target=test_function) for _ in range(THREADS)]
for thread in threads:
    thread.start()
for thread in threads:
    thread.join()

assert m.call_count == LOOPS * THREADS, f"Expected {LOOPS * THREADS}, got {m.call_count}"

Results are something like:

$ python3.14 python_mock_call_count_atomicity.py
Traceback (most recent call last):
  File "python_mock_call_count_atomicity.py", line 21, in <module>
    assert m.call_count == LOOPS * THREADS, f"Expected {LOOPS * THREADS}, got {m.call_count}"
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: Expected 100000, got 95507

This is essentially the same bug as #122957, but that was closed with just a fix to the test suite. This is a bug report that the version of MagicMock for multithreading tests is not thread-safe and so the obvious way of writing those multithreading tests may not work.

CPython versions tested on:

3.14

Operating systems tested on:

Linux

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions