django - 使用 pytest 和 factory-boy,我如何为非传统类型的对象创建工厂?
问题描述
我正在使用 Django 2、Python 3.7 和 factory-boy。试图为 django-address 的 AddressField 创建一个工厂——https://pypi.org/project/django-address/ ,我猜这是一个非传统模型,因为它不继承自models.Model
. 我创建了这个工厂,使用objects = models.Manager()
...
class AddressFactory(factory.DjangoModelFactory):
"""
Define Address Factory
"""
objects = models.Manager()
class Meta:
model = AddressField
street_number = "123"
route = "Rd"
raw = "123 Fake Rd"
formatted = "123 Fake Rd."
latitude = 87.1234
longitude = -100.12342
locality = factory.SubFactory(LocalityFactory)
class CoopFactory(factory.DjangoModelFactory):
"""
Define Coop Factory
"""
class Meta:
model = Coop
name = "test model"
address = factory.SubFactory(AddressFactory)
enabled = True
phone = "312-999-1234"
email = "test@hello.com"
web_site = "http://www.hello.com"
@factory.post_generation
def types(self, create, extracted, **kwargs):
if not create:
# Simple build, do nothing.
return
if extracted:
# A list of types were passed in, use them
for type in extracted:
self.types.add(type)
else:
type = factory.SubFactory(CoopTypeFactory)
self.types.all().set( (type) )
然后我有这个测试......
@pytest.mark.django_db
def test_address_create(self):
""" Test address model """ # create customer model instance
address = AddressFactory()
assert address is not None
但是运行测试会导致以下错误...
davea$ python manage.py test --settings=maps.test_settings
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
setUpTestData: Run once to set up non-modified data for all class methods.
setUp: Run once for every test method to setup clean data.
EsetUp: Run once for every test method to setup clean data.
.
======================================================================
ERROR: test_address_create (tests.test_models.ModelTests)
Test address model
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/factory/django.py", line 126, in _get_manager
manager = model_class.objects
AttributeError: type object 'AddressField' has no attribute 'objects'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/davea/Documents/workspace/chicommons/maps/web/tests/test_models.py", line 27, in test_address_create
address = AddressFactory()
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/factory/base.py", line 46, in __call__
return cls.create(**kwargs)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/factory/base.py", line 564, in create
return cls._generate(enums.CREATE_STRATEGY, kwargs)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/factory/django.py", line 141, in _generate
return super(DjangoModelFactory, cls)._generate(strategy, params)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/factory/base.py", line 501, in _generate
return step.build()
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/factory/builder.py", line 279, in build
kwargs=kwargs,
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/factory/base.py", line 315, in instantiate
return self.factory._create(model, *args, **kwargs)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/factory/django.py", line 184, in _create
manager = cls._get_manager(model_class)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/factory/django.py", line 130, in _get_manager
manager = model_class._default_manager
AttributeError: type object 'AddressField' has no attribute '_default_manager'
我需要做什么来为这种类型的对象建立一个工厂?
编辑:这是我所有荣耀的 Coop 模型......
class Coop(models.Model):
objects = CoopManager()
name = models.CharField(max_length=250, null=False)
types = models.ManyToManyField(CoopType)
address = AddressField(on_delete=models.CASCADE)
enabled = models.BooleanField(default=True, null=False)
phone = PhoneNumberField(null=True)
email = models.EmailField(null=True)
web_site = models.TextField()
解决方案
基本Coop
模型应类似于:
from address.models import AddressField
from django.db import models
class Coop(models.Model):
name = models.CharField(max_length=255)
address = AddressField()
要在测试中配置工厂,您必须为每个模型创建一个工厂django-address
class CountryFactory(factory.DjangoModelFactory):
class Meta:
model = 'address.Country'
name = 'Test Country'
code = '123'
class StateFactory(factory.DjangoModelFactory):
class Meta:
model = 'address.State'
name = 'Test State'
code = '456'
country = factory.SubFactory(CountryFactory)
class LocalityFactory(factory.DjangoModelFactory):
class Meta:
model = 'address.Locality'
name = 'Test Locality'
postal_code = '123'
state = factory.SubFactory(StateFactory)
class AddressFactory(factory.DjangoModelFactory):
class Meta:
model = 'address.Address'
street_number = "123"
route = "Rd"
raw = "123 Fake Rd"
formatted = "123 Fake Rd."
latitude = 87.1234
longitude = -100.12342
locality = factory.SubFactory(LocalityFactory)
class CoopFactory(factory.DjangoModelFactory):
class Meta:
model = Coop
name = 'new Coop'
address = factory.SubFactory(AddressFactory)
测试将是:
class FactoryTest(TestCase):
def test_example(self):
coop_from_factory = CoopFactory()
self.assertIsNotNone(coop_from_factory)
coop = Coop.objects.create(name='test', address=coop_from_factory.address)
self.assertIsNotNone(coop)
推荐阅读
- arrays - 如何使用 Typescript 检查 Array 中的泛型实例
- c# - Linq !Contains() 替代
- nuxt.js - 在特定端口运行 pm2 并使用集群模式
- python - 如何在 python 中读取这个 csv 文件?(每行 3 个逗号 (,,,))
- xamarin.forms - 会话结束时 Xamarin.Forms 获取新令牌
- sql - 在同一行:最后一次购买数量+日期,以及库存总量(几个库存位置) - SQL server
- python - 如何在 Python 的进程池中重复调用相同的函数?
- python - 如何连接其中的音量滑块以使用它
- javascript - 函数从 JS 发送到 PHP
- python - 在python中使用selenium时如何默认最大化chrome浏览器