factoryboy 没有覆盖 django 模型属性

factoryboy not overriding django model properties

我正在尝试通过 factory_boy 覆盖自定义 Django 模型 属性 以进行测试。但它似乎只是采用了模型的默认行为。工厂男孩不能更改自定义属性的默认行为吗?

这是我写的一个基本测试:

models.py:

class Session(models.Model):
    name = models.CharField(max_length=100)

    @property
    def foo(self):
        return method_not_callable_in_testing()

def method_not_callable_in_testing():
    return 42

SessionFactory.py:

class SessionFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = Session

    name = "session"
    foo = 1337

tests.py: class 测试会话(测试用例):

def test_custom_attribute_overwritten_by_factoryboy(self):
    session = SessionFactory.create()
    self.assertEquals(session.foo, 1337)

当 运行 测试时,我得到以下错误:

F
======================================================================
FAIL: test_custom_attribute_overwritten_by_factoryboy (bar.tests.TestSession)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/sh4ke/repos/foo/bar/tests.py", line 10, in test_custom_attribute_overwritten_by_factoryboy
    self.assertEquals(session.foo, 1337)
AssertionError: 42 != 1337

tl;博士

factory_boy 可以改变 "custom attributes",(我假设你的意思是 不是 django Fields),但它不能不要更改只读属性,这正是您正在尝试做的。

更多信息

您的问题是您正在尝试使用工厂为只读 属性 设置属性。粗略地说,factory_boy 和 django 的组合意味着对 SessionFactory() 的调用正在做:

session = Session()
session.foo = 1337

但我不希望它起作用,因为除非你声明 @foo.setter 方法 @property 假设你想要一个只读的 属性,因此当你尝试设置它。

奇怪的是为什么你没有看到那个错误,结果是 django 悄悄地抑制了它!它通过执行 getattr(session, 'foo') 看到您的模型具有 foo 属性,但它已将整个内容 包括 setattr 包裹在 try: except AttributeError:, 所以当它检测并尝试设置一个根本不存在的属性时,它也会捕获并悄悄地忽略尝试设置只读 属性.[=19 的失败案例=]

我怀疑这是一个错误...所以可能会尝试在 django 社区提出它。