The app I am working on is heavily asynchronous. The web application runs a lot of tasks through celery depending on user actions. The celery tasks themselves are capable of launching further tasks.
Code such as the one shown below occurs in our code base quite frequently.
def do_sth():
logic();
if condition:
function1.apply_async(*args)
else:
function2.apply_asynch(*args)
Now we want to start unit testing any new code that we write and we are not sure how to do this. What we would like to assert in our pytest
unit tests is that we want to see if function1 actually got called. We do not want to necessarily run function1
itself as we will have a unit test for the function1
.
I do not want to be running celery as a process, neither do I want to run any AMQP broker during the unit test session.
Is this achievable?
Edit
It was pointed out that this is a duplicate of How do you unit test a Celery task?
It is not. Think about it. What I am asking is how to test if function has called function1 through apply_async. That question is about how do I test function1 itself. There is a major difference. I did hit that question before framing this one.
Process of Task Execution by Celery can be broken down into:Your application sends the tasks to the task broker, it is then reserved by a worker for execution & finally the result of task execution is stored in the result backend.
A typical unit test contains 3 phases: First, it initializes a small piece of an application it wants to test (also known as the system under test, or SUT), then it applies some stimulus to the system under test (usually by calling a method on it), and finally, it observes the resulting behavior.
Have a look at the unittest.mock
module which allows replacing functions you don't want to be invoked with "mocks" which look sufficiently similar to the original functions to convince the calling code that it's invoking the "real thing". You can then check that the mock was actually invoked and with what parameters. Example:
from unittest.mock import patch
def test_do_sth():
with patch('function1.apply_async') as function1_mock:
do_sth()
assert function1_mock.called
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With