I'm wondering if there is a recommended way to stub out BackgroundTasks in unit tests? If I'm running a test for an endpoint I definitely don't want to run any BackgroundTasks that endpoint is creating (e.g. sending emails).
The way I'm doing this right now which seems to work is by creating a wrapper dependency so I can then override it like any other custom dependency. Like this:
def tasks(background_tasks: BackgroundTasks) -> BackgroundTasks:
""" Just a wrapper dependency for BackgroundTasks """
return background_tasks
@router.post("/")
def my_endpoint(background_tasks: BackgroundTasks = Depends(tasks)):
tasks.add_task(...)
Then in my conftest.py I do something like:
@pytest.fixture
def mock_backround_tasks(mocker):
""" The mocked background_tasks dependency """
return mocker.MagicMock(autospec=BackgroundTasks)
app.dependency_overrides[tasks] = lambda: mock_backround_tasks
This feels a bit clunky, I'm wondering if there is a better way to do something like this and if you might add a Testing BackgroundTasks section to the docs with your recommendation?
I encountered the same problem and I use mocker to patch task
def test_success(self, client, mocker):
from api.dependences import feedback
mocker.patch.object(feedback, "send_email_task")
response = client.post('/endpoint', json=data)
assert feedback.send_email_task.called is True
I thought about doing it that way, but how can you be sure the background task is called immediately? Isn鈥檛 it asynchronous? I wouldn鈥檛 want a case where sometimes the test fails because the function hasn鈥檛 been called yet
Yeah, I think Python's own unittest.mock might be useful here: https://docs.python.org/3/library/unittest.mock.html
You could mock the entire BackgroundTasks class in your tests.
And if you want to test the actual functions for the background tasks, you can test them as functions directly too, without having to go through the process of adding them as background tasks.
Assuming the original issue was solved, it will be automatically closed now. But feel free to add more comments or create new issues.
In case people want an example:
with patch("fastapi.BackgroundTasks.add_task") as mock:
def side_effect(*args, **kwargs):
<do something>
mock.side_effect = side_effect
Most helpful comment
In case people want an example: