Django购物车视图测试报错求助:JSON响应及断言失败
Django购物车视图测试问题排查
我正在开发一款Django应用并同步开展测试工作,以下是相关代码及遇到的错误:
视图代码(views.py)
from django.http import JsonResponse, HttpResponseBadRequest from store.models import Product from .basket import Basket # Create your views here. def basket_summary(request): basket = Basket(request) return render(request, "store/basket/summary.html", {"basket": basket}) def basket_add(request): basket = Basket(request) if request.POST.get("action") == "post": product_id = int(request.POST.get("productid")) product_qty = int(request.POST.get("productqty")) product = get_object_or_404(Product, id=product_id) basket.add(product=product, product_qty=product_qty) basket_qty = basket.__len__() response = JsonResponse({"qty": basket_qty}) return response def basket_delete(request): basket = Basket(request) if request.POST.get("action") == "post": product_id = int(request.POST.get("productid")) basket.delete(product_id=product_id) basket_qty = basket.__len__() basket_total = basket.get_total_price() response = JsonResponse({"qty": basket_qty, "subtotal": basket_total}) return response def basket_update(request): basket = Basket(request) if request.POST.get("action") == "post": product_id = int(request.POST.get("productid")) product_qty = int(request.POST.get("productqty")) basket.update(product_id=product_id, product_qty=product_qty) basket_qty = basket.__len__() basket_total = basket.get_total_price() response = JsonResponse({"qty": basket_qty, "subtotal": basket_total}) return response
URL配置(urls.py)
from .views import basket_summary, basket_add, basket_delete, basket_update app_name = "store_basket" urlpatterns = [ path("", basket_summary, name="basket_summary"), path("add/", basket_add, name="basket_add"), path("delete/", basket_delete, name="basket_delete"), path("update/", basket_update, name="basket_update"), ]
测试代码(test_views.py)
from django.contrib.auth.models import User from django.test import TestCase from django.urls import reverse from store.models import Category, Product from json import loads class TestBasketView(TestCase): def setUp(self): category = Category.objects.create(name="django", slug="django") user = User.objects.create(username="admin") Product.objects.create( title="django beginners", category=category, created_by=user, slug="django-beginners", price="20.00", image="django", ) Product.objects.create( title="django intermediate", category=category, created_by=user, slug="django-beginners", price="20.00", image="django", ) Product.objects.create( title="django advanced", category=category, created_by=user, slug="django-beginners", price="20.00", image="django", ) self.client.post( reverse("store_basket:basket_add"), {"productid": 1, "productqty": 1, "action": "post"}, xhr=True, ) self.client.post( reverse("store_basket:basket_add"), {"productid": 2, "productqty": 2, "action": "post"}, xhr=True, ) def test_basket_url(self): """ Test homepage response status """ response = self.client.get(reverse("store_basket:basket_summary")) self.assertEqual(response.status_code, 200) def test_basket_add(self): """ Test adding items to the basket """ response = self.client.post( reverse("store_basket:basket_add"), {"productid": 3, "productqty": 1, "action": "post"}, xhr=True, ) self.assertEqual(response.json(), {"qty": 4}) response = self.client.post( reverse("store_basket:basket_add"), {"productid": 2, "productqty": 1, "action": "post"}, xhr=True, ) self.assertEqual(response.json(), {"qty": 3}) def test_basket_delete(self): """ Test deleting items from the basket """ response = self.client.post( reverse("store_basket:basket_delete"), {"productid": 2, "action": "post"}, xhr=True, ) self.assertEqual(response.json(), {"qty": 1, "subtotal": "20.00"}) def test_basket_update(self): """ Test updating items from the basket """ response = self.client.post( reverse("store_basket:basket_update"), {"productid": 2, "productqty": 1, "action": "post"}, xhr=True, ) self.assertEqual(response.json(), {"qty": 2, "subtotal": "40.00"})
测试错误信息
====================================================================== ERROR: test_basket_add (store_basket.test.test_views.TestBasketView.test_basket_add) Test adding items to the basket ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/bottgabriel/Desktop/Practices/py/ecommerce/store_basket/test/test_views.py", line 63, in test_basket_add self.assertEqual(response.json(), {"qty": 4}) ^^^^^^^^^^^^^^^ File "/Users/bottgabriel/Desktop/Practices/py/ecommerce/venv/lib/python3.11/site-packages/django/test/client.py", line 823, in _parse_json raise ValueError( ValueError: Content-Type header is "text/html; charset=utf-8", not "application/json" ====================================================================== FAIL: test_basket_delete (store_basket.test.test_views.TestBasketView.test_basket_delete) Test deleting items from the basket ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/bottgabriel/Desktop/Practices/py/ecommerce/store_basket/test/test_views.py", line 80, in test_basket_delete self.assertEqual(response.json(), {"qty": 1, "subtotal": "20.00"}) AssertionError: {'qty': 0, 'subtotal': 0} != {'qty': 1, 'subtotal': '20.00'} - {'qty': 0, 'subtotal': 0} ? ^ + {'qty': 1, 'subtotal': '20.00'} ? ^ ++ ++++ ====================================================================== FAIL: test_basket_update (store_basket.test.test_views.TestBasketView.test_basket_update) Test updating items from the basket ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/bottgabriel/Desktop/Practices/py/ecommerce/store_basket/test/test_views.py", line 91, in test_basket_update self.assertEqual(response.json(), {"qty": 2, "subtotal": "40.00"}) AssertionError: {'qty': 0, 'subtotal': 0} != {'qty': 2, 'subtotal': '40.00'} - {'qty': 0, 'subtotal': 0} ? ^ + {'qty': 2, 'subtotal': '40.00'} ? ^ ++ ++++ ---------------------------------------------------------------------- Ran 13 tests in 0.267s FAILED (failures=2, errors=1, skipped=1) Destroying test database for alias 'default'...
我已调试确认视图返回的是JSON,但测试仍无法正常运行,恳请帮助!
问题排查与解决方案
1. 修复视图缺失的导入
视图代码存在两处关键导入缺失,会导致运行时错误并返回HTML错误页面:
basket_summary函数使用render但未导入:添加from django.shortcuts import renderbasket_add函数使用get_object_or_404但未导入:添加from django.shortcuts import get_object_or_404
修改后的视图头部代码:
from django.http import JsonResponse, HttpResponseBadRequest from django.shortcuts import render, get_object_or_404 from store.models import Product from .basket import Basket
2. 移除测试中弃用的xhr=True参数
Django测试客户端的xhr参数已被弃用,且你的视图是从request.POST获取表单数据,而非解析JSON请求。删除所有测试post请求中的xhr=True,确保请求以表单编码方式提交。
示例修改:
self.client.post( reverse("store_basket:basket_add"), {"productid": 1, "productqty": 1, "action": "post"}, )
3. 修复测试数据的重复slug问题
setUp中创建的三个Product使用了相同的slug="django-beginners",即使Django默认不强制slug唯一,也可能导致后续逻辑异常。给每个产品设置唯一slug:
Product.objects.create( title="django intermediate", category=category, created_by=user, slug="django-intermediate", price="20.00", image="django", ) Product.objects.create( title="django advanced", category=category, created_by=user, slug="django-advanced", price="20.00", image="django", )
4. 检查Basket类的核心方法实现
测试返回qty=0和subtotal=0说明Basket类的方法可能未正确操作会话数据:
- 确认
__len__方法是否遍历购物车所有商品,返回总数量而非商品种类数 - 确认
delete方法是否正确从会话中移除对应product_id的条目 - 确认
get_total_price方法是否返回字符串格式的金额(如"20.00")而非数字类型,与测试断言匹配
内容的提问来源于stack exchange,提问作者Cwei0
相关产品推荐
相关产品推荐

