我有一个非常简单的观点如下
def simple_view(request):
documents = request.user.document_set.all()
return render(request, 'simple.html', {'documents': documents})
要在我的测试用例中测试上面的视图,我有以下方法出错。
Class SomeTestCase(TestCase):
# ...
def test_simple_view(self):
# ... some other checks
docset = self.resonse.context['documents']
self.assertTrue(self.user.document_set.all() == docset) # This line raises an error
# ...
我得到的错误是AssertionError: False is not true
。
我尝试打印两个查询集,两者完全相同。当两个对象相同时,为什么会返回False
?任何想法?
目前为了解决这个问题,我正在使用一个讨厌长度的讨厌的黑客:
ds1, ds2 = self.response.context['documents'], self.user.document_set.all()
self.assertTrue(len([x for x in ds1 if x in ds2]) == len(ds1) == len(ds2)) # Makes sure each entry in ds1 exists in ds2
答案 0 :(得分:24)
如果查询集对象是不同查询的结果,则它们将不相同,即使它们的结果中具有相同的值(比较ds1.query
和ds2.query
)。
如果您首先将查询集转换为列表,您应该能够进行正常比较(假设它们当然具有相同的排序顺序):
self.assertEqual(list(ds1), list(ds2))
答案 1 :(得分:6)
此替代方案不需要排序:
self.assertQuerysetEqual(qs1, list(qs2), ordered=False)
请参阅assert reference。
注意:仅适用于django 1.4 +。
答案 2 :(得分:0)
找到解决方案。在我们比较它们之前,我们需要将Querysets
转换为已排序的列表。事情如下。
Class SomeTestCase(TestCase):
# ...
def test_simple_view(self):
# ... some other checks
docset1 = self.resonse.context['documents']
docset2 = self.user.document_set.all()
self.assertTrue(list(sorted(docset1)) == len(sorted(docset)))
# ...
答案 3 :(得分:0)
对我来说,可以使用transform
选项:
def subject(self):
return Mission.objects.add_keynest_api_token().filter(keynest_api_token__isnull=False)
def test_mission_has_property(self):
self.mission.appartement = self.property
self.mission.save()
self.assertQuerysetEqual(self.subject(), [self.mission], transform=lambda x: x)
答案 4 :(得分:0)
您可以使用 assertQuerysetEqual 方法来比较两个查询集,而无需转换为列表。如果查询集的值相等,则无论查询是否不同,这都将返回 True
。
一个问题是,该方法在比较之前将 repr
函数作为对第一个参数中的每个对象的转换,这在比较两个实际相等的查询集时可能会导致以下错误:
AssertionError: Lists differ: ['<Object: id1'] != [<Object: id1>]
解决方案是传递您自己的 transform
函数以代替 repr
使用:
self.assertQuerysetEqual(qs1, qs2, transform=lambda x: x)