【问题标题】:Why does FactoryBoy create a new object from SubFactory despite FACTORY_DJANGO_GET_OR_CREATE尽管 FACTORY_DJANGO_GET_OR_CREATE,为什么 FactoryBoy 从 SubFactory 创建一个新对象
【发布时间】:2013-06-16 21:34:21
【问题描述】:

我刚刚开始在 Django 中使用factory boy。它有一个设置FACTORY_DJANGO_GET_OR_CREATE,这意味着如果已经存在一个新对象,它就不会创建一个新对象。但是,当我使用现有 SubFactory 对象请求现有对象时,尽管有此设置,它仍会创建一个未使用的对象。

例如,在一个全新的项目中,我尝试过:

# models.py
from django.db import models

class A(models.Model):
    name = models.CharField(max_length=10)

class B(models.Model):
    name = models.CharField(max_length=10)
    a = models.ForeignKey(A)

# factories.py
import factory

from . import models

class AFactory(factory.DjangoModelFactory):
    FACTORY_FOR = models.A
    FACTORY_DJANGO_GET_OR_CREATE = ('name',)

    name = factory.Sequence(lambda n: 'A-{0}'.format(n))

class BFactory(factory.DjangoModelFactory):
    FACTORY_FOR = models.B
    FACTORY_DJANGO_GET_OR_CREATE = ('name',)

    name = factory.Sequence(lambda n: 'B-{0}'.format(n))
    a = factory.SubFactory(AFactory)

现在:

from factories import *

a = AFactory(name="Apple")
models.A.objects.all()
# one object
b = BFactory(a__name="Apple", name="Beetle")
models.B.objects.all()
models.A.objects.all()
# one A object, one B object
b = BFactory(name="Beetle")
models.B.objects.all()
models.A.objects.all()
# still one B object, but now a new, unused A object too

然后对BFactory 的最终调用产生了A 类的新对象,尽管名为Beetle 的B 对象已经存在(并且没有重新创建)。为什么,以及如何停止创建这个新的 A 对象?

(我知道我可以通过调用来解决这个问题:

b = BFactory(name="Beetle", a__name="Apple")

但在我的实际用例中,我有几个依赖项和层次结构级别,以这种方式提供额外的冗余参数很麻烦 - 而且我似乎无法获得正确的参数组合。)

谢谢!

【问题讨论】:

    标签: django unit-testing factory-boy


    【解决方案1】:

    当我也有一个类 C 有一个外键到 B 时,上面是一个问题。当我像这样创建一个新的 CFactory 对象时:

    c = CFactory(name="Cat", b__name="Beetle")
    

    它还会创建一个新的未使用的A 对象。

    我发现解决这个问题的方法很简单:改为像这样创建新的 CFactory 对象:

    c = CFactory(name="Cat", b=b)
    

    其中bB 对象或BFactory 对象。

    【讨论】:

      【解决方案2】:

      你可以调用 use:

      a = SubFactory(AFactory, name='Reuse this model A instance')
      

      这样下面的两个调用是相等的:

      BFactory()
      BFactory(a__name='Reuse this model A instance')
      

      【讨论】:

        【解决方案3】:

        我相信子工厂会在 get_or_create 之后启动。

        虽然不确定解决方案,但这不是我遇到的用例。恕我直言,依赖 get_or_create 的装置具有太多的魔法潜力。如果您有一个复杂的测试用例,替代方案(总是创建)可能会更乏味,但更安全

        【讨论】:

        • 谢谢!假设 A 是用户,B 是帖子。使用上面的代码,如果我创建一个新帖子,它总是会创建一个新用户并将帖子与该新用户相关联。我可以使用factory boy 来测试一个用户的多个帖子吗?
        • 我意识到我的评论不清楚 - 如果您像我上面那样设置FACTORY_DJANGO_GET_OR_CREATE,那么一个用户有多个帖子很容易。但我实际上有用户拥有企业,企业发布帖子(即有第三类 C)。事实上,帖子中也可以有其他带有ForeignKeys 的对象(D 类、E 类...)。因此,每次创建这些下游对象之一时,我都会获得新创建(和未使用)对象的整个层次结构。这就是我想避免的。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-01-15
        • 1970-01-01
        • 2021-08-11
        • 2019-06-20
        • 1970-01-01
        • 1970-01-01
        • 2019-04-21
        相关资源
        最近更新 更多