factory boy 工厂中错误的继承行为

Wrong inheritance behavior in factory boy factories

我有几个工厂结构是这样的:

AbstractFactoryMinimal(DjangoModelFactory):
    comment = ''

AbstractFactoryFull(AbstractFactoryMinimal):
    comment = Faker(provider='text', max_nb_chars=2000)

FactoryMinimal(AbstractFactoryMinimal):
    field = ''

    class Meta(object):
        model = SomeModel

FactoryFull(FactoryMinimal, AbstractFactoryFull):
    field = Faker(provider='text', max_nb_chars=2000)

obj = FactoryFull()
print(obj.comment) # expect some text from faker, but got '' instead
print(obj.field)   # works like expected, return some random text

在模型中我有

AbstractModel(TimeStampedModel)

SomeModel(AbstractModel)

我什至看了 mro,它看起来和我预期的一样:

(FactoryFull,
FactoryMinimal,
AbstractFactoryFull,
AbstractFactoryMinimal,
factory.django.DjangoModelFactory,
factory.base.Factory,
factory.base.BaseFactory,
object)

所以 "comment" 字段应该由 faker 生成,而不仅仅是设置为 ''。为什么这样工作?我如何实施工厂才能看到预期的行为?

编辑: 我可以将上一个工厂中的继承顺序更改为:

FactoryFull(AbstractFactoryFull, FactoryMinimal)

它会起作用,但是如果我想覆盖 FactoryMinimal 中的字段,它就不会起作用。有时我正是需要这个功能。无论如何,这首先不是 Python 中的正常继承行为。

# Scan the inheritance chain, starting from the furthest point,
# excluding the current class, to retrieve all declarations.
for parent in reversed(self.factory.__mro__[1:]):
    ...

原因你可以看上面。还要检查此提交中的测试 https://github.com/FactoryBoy/factory_boy/commit/e2ef7c96ed74b35b9dec75a7f222b6ffa9214c10 我很怀疑为什么会这样。也许向这个库的作者询问动机?

所以我找到了一些解决方法。

基本上,我改变了继承顺序并重复了一些代码。像这样:

FactoryMinimal(AbstractFactoryMinimal):
    field = ''

    class Meta(object):
        model = SomeModel

FactoryFull(AbstractFactoryFull, FactoryMinimal):
    field = Faker(provider='text', max_nb_chars=2000)

    class Meta(object):
        model = SomeModel

如果我需要覆盖基础 class 中的某些内容,我会为此使用 MixIn class:

CommentFieldMixIn(DjangoModelFactory):
    comment = 'Something Completely Different'

FactoryMinimal(AbstractFactoryMinimal):
    field = ''

    class Meta(object):
        model = SomeModel

FactoryFull(CommentFieldMixIn, AbstractFactoryFull, FactoryMinimal):
    field = Faker(provider='text', max_nb_chars=2000)

    class Meta(object):
        model = SomeModel

只剩下一个问题:我怎么能说任何维护我的代码的人为什么我在每个工厂都这样做。