如何正确使用Get与Post测试?Post后Get请求返回404问题排查
问题
我编写了如下Get与Post测试代码:
def test_post_product(self): data = { 'title': 'Chicken Breast', 'proteins': 24.00, 'carbs': 0.00, 'fats': 3.00, 'calories': 113 } response = self.client.post(reverse('product-list'), data=json.dumps(data), content_type='application/json') self.assertEqual(HTTP_201_CREATED, response.status_code) url = reverse('product-detail', kwargs={'pk':1}) response = self.client.get(url) self.assertEqual(HTTP_200_OK, response.status_code) self.assertEqual(ProductSerializer(data).data, response.data)
但执行self.assertEqual(HTTP_200_OK, response.status_code)时返回404状态码。而仅包含Get请求的同类测试运行正常:
def test_get_product(self): product1 = Product.objects.create(title='Chicken Breast',proteins=24.00,carbs=0.00,fats=3.00,calories=113) product2 = Product.objects.create(title='Tomatoes', proteins=0.90,carbs=3.90,fats=0.20, calories=18) url = reverse('product-list') response = self.client.get(url) self.assertEqual(HTTP_200_OK, response.status_code) self.assertEqual(ProductSerializer([product1, product2], many=True).data, response.data) url = reverse('product-detail', kwargs={'pk':1}) response = self.client.get(url) self.assertEqual(HTTP_200_OK, response.status_code) self.assertEqual(ProductSerializer(product1).data, response.data)
请问我哪里操作有误?
分析与解决
核心问题是你硬编码了pk=1来获取刚创建的产品,这在测试环境中完全不可靠:
- Django的测试用例会为每个测试方法创建独立事务,测试结束后回滚,但数据库的自增序列不会每次都重置为1。如果测试类中有其他方法先执行并创建过对象,或者
setUp方法里有创建操作,POST生成的产品主键就不会是1。 - 即便没有前置操作,直接依赖自增主键的初始值也是不严谨的测试习惯。
修正步骤
- 从POST响应中获取实际主键:POST请求返回201状态时,响应数据通常会包含刚创建对象的主键(比如
id字段),用这个值构造详情URL。 - 用数据库中实际对象做序列化对比:直接用原始请求数据序列化后对比可能出错,因为序列化器可能自动添加
id、时间戳等字段,应该从数据库取出刚创建的对象再序列化对比。
修改后的测试代码:
def test_post_product(self): data = { 'title': 'Chicken Breast', 'proteins': 24.00, 'carbs': 0.00, 'fats': 3.00, 'calories': 113 } post_response = self.client.post(reverse('product-list'), data=json.dumps(data), content_type='application/json') self.assertEqual(HTTP_201_CREATED, post_response.status_code) # 从POST响应中提取实际主键 created_product_id = post_response.data['id'] detail_url = reverse('product-detail', kwargs={'pk': created_product_id}) get_response = self.client.get(detail_url) self.assertEqual(HTTP_200_OK, get_response.status_code) # 从数据库取出对象,序列化后对比 created_product = Product.objects.get(id=created_product_id) self.assertEqual(ProductSerializer(created_product).data, get_response.data)
这样就能避免硬编码主键带来的404问题,同时保证对比数据的准确性。
内容的提问来源于stack exchange,提问作者hegizt
相关产品推荐
相关产品推荐

