在 Django 中模拟模型字段验证器

Posted

技术标签:

【中文标题】在 Django 中模拟模型字段验证器【英文标题】:Mock out a model field validator in Django 【发布时间】:2020-02-08 01:44:39 【问题描述】:

根据 python 模拟库的文档。我们从正在使用/调用它的模块中模拟出一个函数。

a.py
def function_to_mock(x):
   print('Called function to mock')

b.py
from a import function_to_mock

def function_to_test(some_param):
    function_to_mock(some_param)

# According to the documentation 
#if we want to mock out function_to_mock in a
# test we have to patch it from the b.py module because that is where 
# it is called from

class TestFunctionToTest(TestCase):

    @patch('b.function_to_mock')
    def test_function_to_test(self, mock_for_function_to_mock):
        function_to_test()
        mock_for_function_to_mock.assert_called_once()
   
# this should mock out function to mock and the assertion should work

我让自己陷入了无法确切知道如何模拟相关函数的情况。 情况如下。

# some application
validators.py
def validate_a_field(value):
    # do your validation here.

models.py
from .validators import validate_a_field

class ModelClass(models.Model):
      a_field = models.CharField(max_length=25, validators=[validate_a_field])

forms.py
class ModelClassModelForm(forms.ModelForm):
      class Meta:
           model = ModelClass
           fields = ['a_field',]

Finally in my tests.py
tests.py

class TestModelClassModelForm(TestCase):
      @patch('models.validate_a_field') <<< What to put here ???
      def test_valid_data_validates(self, validate_a_field_mock):
           data = 'a_field':'Some Text'
           validate_a_field_mock.return_value = True

           form = ModelClassModelForm(data=data)
           is_valid = form.is_valid()
           validate_a_field_mock.assert_called_once() <<< This is failing

尽管 validate_a_field 在 models.py 中被调用,但据我所知。当验证发生时,它永远不会从那里使用。 因此,当我修补为 models.validate_a_field

时,它不会被嘲笑

我最好的猜测是它在django.forms.field 的某个地方被调用。 但我不知道如何或在哪里。

有谁知道如何解决这个难题?我必须嘲笑 validate_a_field 因为它确实调用了更多的外部 API 集成测试。我想写一个单元测试。

【问题讨论】:

【参考方案1】:

如果我有选择,我会修补 ModelClass.full_clean 方法

class TestModelClassModelForm(TestCase):

    @patch('sample.models.ModelClass.full_clean')
    def test_valid_data_validates(self, mock_model_full_clean):
        data = 'a_field': 'Some Text'
        form = ModelClassModelForm(data=data)
        is_valid = form.is_valid()

        mock_model_full_clean.assert_called_once()
        self.assertTrue(is_valid)
        self.assertDictEqual(data, form.cleaned_data)

【讨论】:

以上是关于在 Django 中模拟模型字段验证器的主要内容,如果未能解决你的问题,请参考以下文章

可以在 django 模型验证器中使用多个值吗?

如何在 django rest 框架 ModelSerializer 中覆盖模型字段验证

无法在 Django Rest Framework 序列化程序的验证数据中获取非模型字段

Django 验证

Django 1.8.3 - 具有相关对象的模型字段验证

Django 模型条件验证