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
只剩下一个问题:我怎么能说任何维护我的代码的人为什么我在每个工厂都这样做。
我有几个工厂结构是这样的:
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
只剩下一个问题:我怎么能说任何维护我的代码的人为什么我在每个工厂都这样做。