39

我正在尝试测试我的 Django 视图。此视图将 QuerySet 传递给模板:

def merchant_home(request, slug):
  merchant = Merchant.objects.get(slug=slug)
  product_list = merchant.products.all()
  return render_to_response('merchant_home.html',
                            {'merchant': merchant,
                            'product_list': product_list},
                            context_instance=RequestContext(request))

并测试:

  def test(self):
    "Merchant home view should send merchant and merchant products to the template"
    merchant = Merchant.objects.create(name='test merchant')
    product = Product.objects.create(name='test product', price=100.00)
    merchant.products.add(product)

    test_client = Client()
    response = test_client.get('/' + merchant.slug)
    # self.assertListEqual(response.context['product_list'], merchant.products.all())
    self.assertQuerysetEqual(response.context['product_list'], merchant.products.all())

编辑 我使用self.assertQuerysetEqual 而不是self.assertListEqual. 不幸的是,这仍然不起作用,终端显示: ['<Product: Product object>'] != [<Product: Product object>]


assertListEqualraises:'QuerySet' object has no attribute 'difference'assertEqual不起作用,尽管self.assertSetEqual(response.context['product_list'][0], merchant.products.all()[0])确实通过了。

我认为这是因为 QuerySets 是不同的对象,即使它们包含相同的模型实例。

如何测试两个 QuerySet 是否包含相同的数据?我什至正确地测试了这个?这是我学习 Django 的第四天,所以如果可能的话,我想知道最佳实践。谢谢。

4

6 回答 6

43

默认情况下assertQuerysetEqual使用repr()第一个参数。这就是您在查询集比较中遇到字符串问题的原因。

要解决此问题,您可以使用不使用的函数覆盖transform参数lambdarepr()

self.assertQuerysetEqual(queryset_1, queryset_2, transform=lambda x: x)
于 2018-03-06T11:17:18.023 回答
34

使用assertQuerysetEqual,它是为您比较两个查询集而构建的。您需要对 Django 进行子类化django.test.TestCase才能在您的测试中使用它。

于 2013-07-16T19:15:35.757 回答
10

我只是有同样的问题。的第二个参数assertQuerysetEqual需要是作为字符串的预期 repr() 列表。这是 Django 测试套件中的一个示例:

self.assertQuerysetEqual(c1.tags.all(), ["<Tag: t1>", "<Tag: t2>"], ordered=False)
于 2013-12-15T16:00:03.880 回答
4

使用 pytest 时,另一种但不一定更好的方法可能看起来像这样(例如,在视图中测试上下文):

all_the_things = Things.objects.all()
assert set(response.context_data['all_the_things']) == set(all_the_things)

这会将其转换为一个集合,可以直接与另一个集合进行比较。但是要小心它的行为set,它可能不是您想要的,因为它会删除重复项并忽略对象的顺序。

于 2016-07-26T14:42:03.800 回答
4

我最终解决了这个问题,使用调用中查询集中maprepr()每个条目self.assertQuerysetEqual,例如

self.assertQuerysetEqual(queryset_1, map(repr, queryset_2))
于 2018-03-23T14:00:57.270 回答
0

我发现使用self.assertCountEqual(queryset1, queryset2)也解决了这个问题。

于 2018-05-10T02:04:40.660 回答