gpt4 book ai didi

python - 如何使用 Mock 库模拟 Django ForeignKey 值?

转载 作者:太空狗 更新时间:2023-10-29 21:07:30 29 4
gpt4 key购买 nike

我有一个模型,我正在尝试在不调用数据库层的情况下测试验证。我不会用文字描述,而是会发布一些示例代码。这里的问题是 ForeignKey 与 Bar 的关系,它与我要测试的内容无关,但阻止我运行我想要的测试。

首先,myapp/models.py:

from django.core.exceptions import ValidationError
from django.db import models


class BadFooError(ValidationError):
pass


class Bar(models.Model):
description = models.CharField(max_length=20)


class Foo(models.Model):
bar = models.ForeignKey(Bar)

a_value = models.IntegerField()

b_value = models.BooleanField()

def clean(self):
super(Foo, self).clean()
if self.b_value and self.a_value > 50:
raise BadFooError("No good")

接下来,myapp/tests.py:

from unittest import TestCase

from mock import MagicMock

from . import models


class SimpleTest(TestCase):

def test_avalue_bvalue_validation(self):
foo = models.Foo()
foo.a_value = 30
foo.b_value = True
foo.bar = MagicMock(spec=models.Bar)
self.assertRaises(models.BadFooError, foo.full_clean)

def test_method_2(self):
foo = models.Foo()
foo.a_value = 30
foo.b_value = True
foo.bar = MagicMock()
foo.__class__ = models.Bar
self.assertRaises(models.BadFooError, foo.full_clean)

def test_method_3(self):
foo = models.Foo()
foo.a_value = 30
foo.b_value = True
# ignore it and it will go away ...??
self.assertRaises(models.BadFooError, foo.full_clean)

最后,python manage.py test myapp

的输出
EEE
======================================================================
ERROR: test_avalue_bvalue_validation (myapp.tests.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "~/sandbox/myapp/tests.py", line 14, in test_avalue_bvalue_validation
foo.bar = MagicMock(spec=models.Bar)
File "~/dsbx/local/lib/python2.7/site-packages/django/db/models/fields/related.py", line 408, in __set__
instance._state.db = router.db_for_write(instance.__class__, instance=value)
File "~/dsbx/local/lib/python2.7/site-packages/django/db/utils.py", line 142, in _route_db
return hints['instance']._state.db or DEFAULT_DB_ALIAS
File "~/dsbx/local/lib/python2.7/site-packages/mock.py", line 658, in __getattr__
raise AttributeError("Mock object has no attribute %r" % name)
AttributeError: Mock object has no attribute '_state'

======================================================================
ERROR: test_method_2 (myapp.tests.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "~/sandbox/myapp/tests.py", line 21, in test_method_2
foo.bar = MagicMock()
File "~/dsbx/local/lib/python2.7/site-packages/django/db/models/fields/related.py", line 405, in __set__
self.field.name, self.field.rel.to._meta.object_name))
ValueError: Cannot assign "<MagicMock id='31914832'>": "Foo.bar" must be a "Bar" instance.

======================================================================
ERROR: test_method_3 (myapp.tests.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "~/sandbox/myapp/tests.py", line 29, in test_method_3
self.assertRaises(models.BadFooError, foo.full_clean)
File "/usr/lib/python2.7/unittest/case.py", line 471, in assertRaises
callableObj(*args, **kwargs)
File "~/dsbx/local/lib/python2.7/site-packages/django/db/models/base.py", line 926, in full_clean
raise ValidationError(errors)
ValidationError: {'bar': [u'This field cannot be null.']}

----------------------------------------------------------------------
Ran 3 tests in 0.003s

FAILED (errors=3)
Creating test database for alias 'default'...
Destroying test database for alias 'default'...

所以我的问题是……怎么办?

最佳答案

在我的单元测试中,我只是将 _state 分配给一个新的 Mock 实例,就像对您的第一个示例单元测试的这个小改动一样:

def test_avalue_bvalue_validation(self):
foo = models.Foo()
foo.a_value = 30
foo.b_value = True
bar = Mock(spec=models.Bar)
bar._state = Mock()
foo.bar = bar
self.assertRaises(models.BadFooError, foo.full_clean)

但是,为了将您的验证作为黑盒进行测试,我会将验证代码提取到您模型上的一个单独方法中,我将从 clean() 方法内部调用该方法。然后,您可以专门对该验证代码进行单元测试。您仍然需要执行 _stage = Mock() 分配,以便您可以创建 Foo 的实例,但至少您将最大限度地减少对 Django 的调用。

关于python - 如何使用 Mock 库模拟 Django ForeignKey 值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16847332/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com