Django补丁副作用IntegrityError未被引发

时间:2016-10-10 10:44:45

标签: python django mocking

我有以下视图,除了POST请求,并序列化对象数据(Draftschedule)以创建新副本(FrozenSchedule):

from reports.tasks import create_frozen_schedule

def freeze_schedule(request, pk):
    """Valid post request will freeze a Draft Schedule serializing its data"""
    client = get_object_or_404(Client, draftschedule=pk)
    try:
        # Serialize data into a FrozenSchedule object
        frozenschedule = create_frozen_schedule(pk, request.user.id)
    except IntegrityError:
        # Warn user if action failed
        messages.warning(request, "A Schedule of this Type already exists")
        return redirect(client.draftschedule)
    else:
        # If Schedule is Frozen successfully
        messages.success(request, "Schedule Frozen")
        return redirect(frozenschedule)

我尝试编写测试来断言在引发IntegrityError之后发生某些事情。我很难理解为什么它会失败,但是在我出错的地方并不是很明显,因为我对嘲弄/打补丁相当缺乏经验。

我试图在调用时模拟create_frozen_schedule函数来引发IntegrityError:

def setUp(self):
    self.url = reverse(
        'reports:draftschedule-freeze',
        args=[self._client.draftschedule.pk]
    )
    super(TestFreezeSchedule, self).setUp()


@patch('reports.tasks.create_frozen_schedule')
def test_freeze_schedule_with_conflict(self, mock_freeze):
    mock_freeze.side_effect = IntegrityError
    with self.assertRaises(IntegrityError):
        self.client.post(self.url)

   # More unit tests following same premise...

但我最终得到以下错误:

.......................................................................................F............
======================================================================
FAIL: test_freeze_schedule_with_conflict (reports.tests.test_views.TestFreezeSchedule)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python3.4/unittest/mock.py", line 1136, in patched
    return func(*args, **keywargs)
  File "/home/jwe/piesup2/reports/tests/test_views.py", line 495, in test_freeze_schedule_with_conflict
    self.client.post(self.url)
AssertionError: IntegrityError not raised

----------------------------------------------------------------------

注意事项:

  • 我能够在我的实际Django网站上的测试之外复制此错误。
  • 我故意省略了create_frozen_schedule代码 序列化是相当冗长的,我的理解是 实施细节无论如何都不重要,因为我嘲笑了 功能
  • IntegrityError本身的目的是防止重复FrozenSchedule个对象,其Meta类如下所示:

    class Meta:
        # ...
        unique_together = ('client', 'data',)
    

为什么副作用没有被提出的任何想法?

2 个答案:

答案 0 :(得分:1)

您的视图捕获IntegrityError并返回重定向。客户端帖子就是您的测试所调用的,根本不会引发错误。

相反,您应该测试except块中的操作是否发生:是警告集,并且帖子是否重定向到草稿计划而不是冻结计划。

答案 1 :(得分:0)

如果你想真正测试你的函数抛出异常,你需要直接测试函数而不是POST。类似的东西:

from django.test import RequestFactory

@patch('reports.tasks.create_frozen_schedule')
def test_freeze_schedule_with_conflict(self, mock_freeze):
    mock_freeze.side_effect = IntegrityError
    myrequest = RequestFactory().post(*some_url*)
    # you may need to add, e.g., items to myrequest.POST
    with self.assertRaises(IntegrityError):@patch('reports.tasks.create_frozen_schedule')
        freeze_schedule(myrequest, pk)