我正在为一个我正在工作的网站写测试,我用factoryboy工厂对象来表示模型。
然而,我遇到了一些让我感到困惑的行为,我想知道这里是否有人能如此友好地向我解释一下
我正在运行一个包含以下模型的测试:
STATUS = (
('CALCULATING'),
('PENDING'),
('BUSY'),
('SUCCESS'),
('FAILED')
)
class SchoolImport(models.Model):
date = models.DateTimeField(auto_now_add=True)
status = models.CharField(
verbose_name=_('status'), choices=STATUS,
max_length=50, default='CALCULATING'
)为此,我创建了以下工厂。正如您所看到的,status被设置为其缺省值,我发现这比随机选择的值更现实
class SchoolImportFactory(factory.DjangoModelFactory):
class Meta:
model = models.SchoolImport
status = 'CALCULATING'
school = factory.SubFactory(SchoolFactory)
@factory.lazy_attribute
def date(self):
return timezone.now() - datetime.timedelta(days=10)下面您将看到正在测试的函数的(简化)版本,以及测试本身。(我目前已经注释掉了笔记本电脑上的所有其他代码,因此您在下面看到的函数是一个准确的表示)
它的要点是该函数接收到一个id值,它将使用该值从数据库获取SchoolImport对象并更改其状态。该函数将在celery中运行,因此不会返回任何内容。
当我通过调试器运行此测试时,我可以看到该值已正确更改。但是,当测试运行其最终断言时,它会失败,因为self.school_import.status仍然等于CALCULATING。
#app.utils.py
def process_template_objects(school_import_pk):
school_import = models.SchoolImport.objects.get(id=import_file_pk)
school_import.status = 'BUSY'
school_import.save()
#app.tests.test_utils.py
class Test_process_template_objects_function(TestCase):
def setUp(self):
self.school = SchoolFactory()
self.school_import = SchoolImportFactory(
school=self.school
)
def test_function_alters_school_import_status(self):
self.assertEqual(
self.school_import.status, 'CALCULATING'
)
utils.process_template_objects(self.school_import.id)
self.assertNotEqual(
self.school_import.status, 'CALCULATING'
)当我通过调试器(在失败的断言之前有一个断点)运行此测试并运行SchoolImport.objects.get(id=self.school_import.id).status时,它确实返回了正确的BUSY值。
因此,尽管由FactoryInstance表示的对象正在正确更新,但更改不会反映在工厂实例本身中。
虽然我意识到我可能在这里做错了什么/遇到了预期的行为,但我想知道使用factoryboy编写测试的人是如何绕过这种行为的,或者是否有一种方法可以“刷新”factoryboy实例以反映对模型实例的更改。
发布于 2019-08-16 03:22:16
这个问题源于这样一个事实:在process_template_objects中,您使用的SchoolImport对象实例与测试中的实例不同。
如果您运行以下命令:
a = models.SchoolImport.objects.get(pk=1)
b = models.SchoolImport.objects.get(pk=2)
assert a == b # True: both refer to the same object in the database
assert a is b # False: different Python objects, each with its own memory
a.status = 'SUCCESS'
a.save()
assert a.status == 'SUCCESS' # True: it was indeed changed in this Python object
assert b.status == 'SUCCESS' # False: the 'b' object hasn't seen the change为了解决这个问题,您应该在调用process_template_objects之后从数据库中重新获取实例
utils.process_template_objects(self.school_import.id)
self.school_import.refresh_from_db()有关更详细的解释,请参阅https://docs.djangoproject.com/en/2.2/ref/models/instances/#refreshing-objects-from-database!
发布于 2020-01-19 08:16:05
如果从模型实例中删除某个字段,则再次访问该字段时会从数据库中重新加载该值。
obj = MyModel.objects.first()
del obj.field
obj.field # Loads the field from the database请参阅https://docs.djangoproject.com/en/2.2/ref/models/instances/#refreshing-objects-from-database
https://stackoverflow.com/questions/57513453
复制相似问题