Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocking Celery `self.request` attribute for bound tasks when called directly

I have a task foobar:

@app.task(bind=True)
def foobar(self, owner, a, b):
   if already_working(owner): # check if a foobar task is already running for owner.
       register_myself(self.request.id, owner) # add myself in the DB.
   return a + b

How can I mock the self.request.id attribute? I am already patching everything and calling directly the task rather than using .delay/.apply_async, but the value of self.request.id seems to be None (as I am doing real interactions with DB, it is making the test fail, etc…).

For the reference, I'm using Django as a framework, but I think that this problem is just the same, no matter the environment you're using.

like image 955
Raito Avatar asked Oct 29 '17 12:10

Raito


2 Answers

Disclaimer: Well, I do not think it was documented somewhere and this answer might be implementation-dependent.

Celery wraps his tasks into celery.Task instances, I do not know if it swaps the celery.Task.run method by the user task function or whatever.

But, when you call a task directly, you call __call__ and it'll push a context which will contain the task ID, etc…

So the idea is to bypass __call__ and Celery usual workings, first:

  • we push a controlled task ID: foobar.push_request(id=1) for example.
  • then, we call the run method: foobar.run(*args, **kwargs).

Example:

@app.task(bind=True)
def foobar(self, name):
    print(name)
    return foobar.utils.polling(self.request.id)

@patch('foobar.utils.polling')
def test_foobar(mock_polling):
    foobar.push_request(id=1)
    mock_polling.return_value = "done"
    assert foobar.run("test") == "done"
    mock_polling.assert_called_once_with(1)
like image 188
Raito Avatar answered Oct 13 '22 00:10

Raito


You can call the task synchronously using

task = foobar.s(<args>).apply()

This will assign a unique task ID, so the value will not be None and your code will run. Then you can check the results as part of your test.

like image 42
ronathan Avatar answered Oct 13 '22 01:10

ronathan