2015-05-29 29 views
1

我想使用python mock庫來測試我的Django應用程序發送電子郵件。Python:模擬不能在芹菜任務內工作

測試代碼:

# tests.py 
from django.test import TestCase 

class MyTestCase(TestCase): 

    @mock.patch('django.core.mail.mail_managers') 
    def test_canceled_wo_claiming(self, mocked_mail_managers): 
     client = Client() 
     client.get('/') 
     print(mocked_mail_managers.called) 
     mocked_mail_managers.assert_called_with('Hi, managers!', 'Message Body') 

第一個例子 - 無需任務

# views.py 
from django.views.generic import View 
from django.core.mail import mail_managers 

class MyView(View): 

    def get(self, request): 
     mail_managers('Hi, managers!', 'Message Body') 
     return HttpResponse('Hello!') 

第二個例子 - 與任務

# views.py 
from django.views.generic import View 
from . import tasks 

class MyView(View): 
    def get(self, request): 
     tasks.notify.apply_async() 
     return HttpResponse('Hello!') 


# tasks.py 
from celery import shared_task 
from django.core.mail import mail_managers 

@shared_task 
def notify(): 
    mail_managers('Hi, managers!', 'Message Body') 

第一個示例正常,第二封xample失敗,出現Not called異常。

我的設置:

# Celery 
BROKEN_URL = 'memory://' 
BROKER_BACKEND = 'memory' 

CELERY_ALWAYS_EAGER = True 
CELERY_EAGER_PROPAGATES_EXCEPTIONS = True 
TEST_RUNNER = 'djcelery.contrib.test_runner.CeleryTestSuiteRunner' 

是否有可能進行這樣的綜合測試或解決這一問題的唯一辦法是分割測試分爲二?

回答

0

我發現一個問題,它非常愚蠢。 Described hereHere

的基本原則是,你修補的對象中查找,這是不一定相同的地方,因爲它是定義在哪裏。

我需要改變:

@mock.patch('django.core.mail.mail_managers') 

@mock.patch('path.to.tasks.mail_managers') 
2

直接從使用它們的代碼測試異步任務的行爲可能會非常棘手。原因之一是測試可能甚至在任務實際運行之前執行斷言,這可能會給你誤報。我在這種情況下做的事情是將測試分爲兩步:

  1. 嘲笑任務並測試它在被調用時以及期望的參數時被調用。
  2. 將任務作爲獨立函數進行測試,並將其作爲普通函數執行,即不需要芹菜服務器。

爲了說明這一點,這可能是這樣的:

# views.py 
from path.to.tasks import my_task 


def my_view(requtest): 
    # do stuff 
    my_task.delay('foo', 'bar') 
    return HttpResponse('whatever') 


# test_my_task.py 
from views import my_view 
from path.to.tasks import my_task 


class MyTest(TestCase): 
    @mock.patch('path.to.tasks.my_task') 
    def test_my_task_is_called(self, mocked_task): 
     client = Client() 
     client.get('/') 
     my_task.assert_called_with('foo', 'bar') 

    def test_my_task_works(self): 
     my_task('foo', 'bar') # note I don't use .delay(...), .apply_async(...), etc 
     assert 'my task did what I expected it to do' 

這樣你就可以測試你的實現代碼在問候你的任務,該任務能正常運行,一旦如預期它被稱爲正常的行爲。

我希望它很有用! :)