我使用Factory Boy来测试Django项目,并且在测试我已覆盖保存方法的模型时遇到了问题。
模特:
async def async_subprocess_command(*args):
# Create subprocess
process = await asyncio.create_subprocess_exec(
*args,
# stdout must a pipe to be accessible as process.stdout
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE)
# Wait for the subprocess to finish
stdout, stderr = await process.communicate()
# Return stdout and sterr
return stdout.decode().strip(),sterr.decode().strip()
data1a, data1b = await async_subprocess_command(soxExecutable, "--i", audiofilepath)
data2a, data2b = await async_subprocess_command(soxExecutable, audiofilepath,"-n", "stat")
工厂:
class Profile(models.Model):
active = models.BooleanField()
user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE,
related_name='profiles')
department = models.ForeignKey(Department, null=True, blank=True)
category_at_start = models.ForeignKey(Category)
role = models.ForeignKey(Role)
series = models.ForeignKey(Series, null=True, blank=True)
status = models.ForeignKey('Status', Status)
def save(self, *args, **kwargs):
super(Profile, self).save(*args, **kwargs)
active_roles = []
active_status = []
for profile in Profile.objects.filter(user=self.user):
if profile.active:
active_roles.append(profile.role.code)
active_status.append(profile.status.name)
self.user.current_role = '/'.join(set(active_roles))
if 'Training' in active_status:
self.user.current_status = 'Training'
elif 'Certified' in active_status:
self.user.current_status = 'Certified'
else:
self.user.current_status = '/'.join(set(active_status))
self.user.save()
super(Profile, self).save(*args, **kwargs) ### <-- seems to be the issue.
测试:
class ProfileFactory(f.django.DjangoModelFactory):
class Meta:
model = models.Profile
active = f.Faker('boolean')
user = f.SubFactory(UserFactory)
department = f.SubFactory(DepartmentFactory)
category_at_start = f.SubFactory(CategoryFactory)
role = f.SubFactory(RoleFactory)
series = f.SubFactory(SeriesFactory)
status = f.SubFactory(StatusFactory)
当我运行测试时,出现以下错误:
class ProfileTest(TestCase):
def test_profile_creation(self):
o = factories.ProfileFactory()
self.assertTrue(isinstance(o, models.Profile))
如果我评论最后一个/第二个&#39; super&#39;测试通过的Profile保存方法中的语句。我想知道这句话是否试图使用相同的ID再次创建配置文件?我尝试了各种各样的事情,比如在Meta类中指定django_get_or_create和各种黑客版本的覆盖工厂的_generation方法,断开并连接后代保存,但我无法让它工作。
与此同时,我已制定了构建策略,但显然不会测试我的保存方法。
非常感谢任何帮助。
学家
答案 0 :(得分:4)
factory_boy
使用Django的ORM中的MyModel.objects.create()
函数。
该函数调用obj.save(force_insert=True)
:https://github.com/django/django/blob/master/django/db/models/query.py#L384
使用重载的save()
函数,这意味着您得到:
super(Profile, self).save(force_insert=True)
INSERT INTO simtrack_profile SET ...;
] self.pk
设置为新插入行的pk super(Profile, self).save(force_insert=True)
INSERT INTO simtrack_profile SET id=N, ...
,其中N
是对象的pk id=N
。您应该修复save()
功能,以便第二次拨打super(Profile, self).save()
而不再次重复*args, **kwargs
。
Profile.objects.create()
的任何时候,您的代码都会中断。self
函数中修改save()
,因此您应该能够完全删除对super(Profile, self).save()
的第二次调用;虽然保留它可能有助于避免奇怪的错误,如果你以后需要添加更多的自定义行为。