Django的ModelForm和mock.patch.object打破打破单元测试隔离?

时间:2019-02-27 12:24:04

标签: python django unit-testing django-models python-mock

我有一个单元测试,将Django DateTimeField的默认值修补为已知值。此测试通过良好,直到引入基于同一模型创建ModelForm的测试为止,此时原始测试开始失败:

Failure
Traceback (most recent call last):
  File "test_example.py", line 36, in test_init_date_missing
    self.assertEqual(actual.event_datetime, test_dt)
AssertionError: datetime.datetime(2019, 2, 27, 12, 20, 25, 69409) != datetime.datetime(2019, 2, 10, 10, 10, 10)

该测试在相互独立运行时通过,但是一旦我尝试在同一套件中同时运行两者,它就会失败。好像在另一个测试中实例化表单后,修补程序就失败了。

此示例代码演示了该问题:

from datetime import datetime
from unittest import mock

from django import forms
from django.test import TestCase
from django.db import models
from django.utils import timezone


class MyExampleModel(models.Model):
    event_datetime = models.DateTimeField(default=timezone.now)


class MyExampleForm(forms.ModelForm):
    class Meta:
        model = MyExampleModel
        fields = ['event_datetime']


class ExampleTest(TestCase):
    def test_init_date_missing(self):
        """Tests that date is set automatically when not provided"""
        # Little bit of magic to mock the default value of a Django Field
        # Taken from https://stackoverflow.com/questions/18924869/mocking-default-timezone-now-for-unit-tests
        test_dt = datetime(2019, 2, 10, 10, 10, 10)
        event_datetime_field = MyExampleModel._meta.get_field('event_datetime')
        mock_tznow = mock.MagicMock(return_value=test_dt)

        with mock.patch.object(event_datetime_field, 'default', mock_tznow):
            actual = MyExampleModel()

        self.assertEqual(actual.event_datetime, test_dt)
        actual.save()  # The proof is in the pudding, will it actually save?


class ExampleFormTest(TestCase):
    def test_form(self):
        """Commenting out the below line causes ExampleTest.test_init_date_missing to pass
        Uncommmenting causes ExampleTest.test_init_date_missing to fail"""
        MyExampleForm()

为什么会这样? 为了使这些测试很好地配合,我能做些什么?

0 个答案:

没有答案