Skip to content

Commit b4662b2

Browse files
committed
Fix race condition in celery system integration tests
Celery stores the task result before firing the task_success signal. This means result.get() can return before the success handler runs, causing the mock context to exit and the second update_task_safe call to hit the real function instead of the mock. Add _wait_for_mock_calls() to poll until the expected call count is reached before exiting the mock context.
1 parent 4564a2e commit b4662b2

1 file changed

Lines changed: 15 additions & 0 deletions

File tree

tests/test_celery_system_integration.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import logging
1212
import sys
13+
import time
1314
import weakref
1415
from http import HTTPStatus
1516
from unittest import mock
@@ -26,6 +27,18 @@
2627
from tests.utils import task_for_test
2728

2829

30+
def _wait_for_mock_calls(mock_obj, expected_count, timeout=5):
31+
"""Wait for a mock to reach the expected call count.
32+
33+
Celery stores the task result before firing task_success, so
34+
``result.get()`` can return before the success signal handler runs.
35+
Without this wait the mock context may exit before the handler fires.
36+
"""
37+
deadline = time.monotonic() + timeout
38+
while mock_obj.call_count < expected_count and time.monotonic() < deadline:
39+
time.sleep(0.05)
40+
41+
2942
@pytest.fixture()
3043
def _bind_settings_with_system():
3144
systems = [CelerySystemIntegration()]
@@ -71,6 +84,7 @@ def add_normal(self, a, b):
7184
result = add_normal.delay(2, 2)
7285
assert result.info.get("taskbadger_task_id") == tb_task.id
7386
assert result.get(timeout=10, propagate=True) == 4
87+
_wait_for_mock_calls(update, 2)
7488

7589
create.assert_called_once()
7690
assert get_task.call_count == 1
@@ -102,6 +116,7 @@ def add_normal(self, a, b):
102116
result = add_normal.delay(2, 2)
103117
assert result.info.get("taskbadger_task_id") == tb_task.id
104118
assert result.get(timeout=10, propagate=True) == 4
119+
_wait_for_mock_calls(update, 2)
105120

106121
create.assert_called_once_with(
107122
"tests.test_celery_system_integration.add_normal",

0 commit comments

Comments
 (0)