4

我正在开发一个开源 django 网络应用程序,我正在寻找使用 Factory Boy 来帮助我为一些测试设置模型,但是在阅读文档和查看示例几个小时后,我认为我需要接受失败并在这里问。

我有一个看起来有点像这样的客户模型:

class Customer(models.Model):

    def save(self, *args, **kwargs):
        if not self.full_name:
            raise ValidationError('The full_name field is required')
        super(Customer, self).save(*args, **kwargs)


    user = models.OneToOneField(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        related_name='customer',
        null=True
    )

    created = models.DateTimeField()
    created_in_billing_week = models.CharField(max_length=9)
    full_name = models.CharField(max_length=255)
    nickname = models.CharField(max_length=30)
    mobile = models.CharField(max_length=30, default='', blank=True)
    gocardless_current_mandate = models.OneToOneField(
        BillingGoCardlessMandate,
        on_delete=models.SET_NULL,
        related_name='in_use_for_customer',
        null=True,
    )

我还使用来自 django.contrib.auth 的标准 Django 用户模型。

这是我的工厂代码:

class UserFactory(DjangoModelFactory):

    class Meta:
        model = get_user_model()


class CustomerFactory(DjangoModelFactory):

    class Meta:
        model = models.Customer

    full_name = fake.name()
    nickname = factory.LazyAttribute(lambda obj: obj.full_name.split(' ')[0])

    created = factory.LazyFunction(timezone.now)
    created_in_billing_week = factory.LazyAttribute(lambda obj: str(get_billing_week(obj.created)))

    mobile = fake.phone_number()

    user = factory.SubFactory(UserFactory, username=nickname,
        email="{}@example.com".format(nickname))

就我而言,我希望能够产生这样的客户

CustomerFactory(fullname="Joe Bloggs")

并使用正确的用户名和电子邮件地址生成相应的用户。

现在,我收到此错误:

  AttributeError: The parameter full_name is unknown. Evaluated attributes are {'email': '<factory.declarations.LazyAttribute object at 0x111d999e8>@example.com'}, definitions are {'email': '<factory.declarations.LazyAttribute object at 0x111d999e8>@example.com', 'username': <DeclarationWrapper for <factory.declarations.LazyAttribute object at 0x111d999e8>>}.

我认为这是因为我在客户中依赖一个惰性属性,在创建用户工厂之前不会调用它。

如果我希望能够使用工厂来创建 Customer 模型实例,以及如上所述的相应用户,我应该怎么做?

对于它的价值,完整的模型可以在 github repo 上看到

4

1 回答 1

5

在这种情况下,最好的方法是从客户声明中选择值:

class CustomerFactory(DjangoModelFactory):

    class Meta:
        model = models.Customer

    full_name = factory.Faker('name')
    nickname = factory.LazyAttribute(lambda obj: obj.full_name.split(' ')[0])

    created = factory.LazyFunction(timezone.now)
    created_in_billing_week = factory.LazyAttribute(lambda obj: str(get_billing_week(obj.created)))

    mobile = factory.Faker('phone_number')

    user = factory.SubFactory(
        UserFactory,
        username=factory.SelfAttribute('..nickname'),
        email=factory.LazyAttribute(lambda u: "{}@example.com".format(u.username)))
    )

此外,用于factory.Faker('field_name')获取每个实例的随机值:fullname = fake.name() 类声明中的行等效于:

DEFAULT_FULL_NAME = fake.name()

class CustomerFactory(DjangoModelFactory):
    full_name = DEFAULT_FULL_NAME

    class Meta:
        model = models.customer

factory.Faker('name')相当于:

class CustomerFactory(DjangoModelFactory):
    full_name = factory.LazyFunction(fake.name)

    class Meta:
        model = models.customer

iefake.name()将为使用该工厂构建的每个模型提供不同的名称。

于 2016-09-17T16:56:57.943 回答