Django Rest嵌套Serializer测试方法及多对多关联请求排障
解决Django REST Framework嵌套Serializer测试时字段丢失问题
问题根源
你测试时使用self.client.put(path, data)的写法,默认会把data以**表单编码(application/x-www-form-urlencoded)**发送,这种格式无法正确解析嵌套的字典数组结构(比如tasklists里的{"pk": "..."}),导致DRF的解析器无法识别tasklists字段,自然不会出现在validated_data或initial_data中。
正确的测试请求写法
必须显式指定请求的content_type为application/json,并将数据序列化为JSON字符串传递:
import json from django.test import TestCase class TaskUpdateTestCase(TestCase): def test_update_task_associated_lists(self): path = self.task.get_absolute_api_url() data = { "title": "hello", "tasklists": [ {"pk": "b84d3375-0e09-4dd1-9809-f92d29d6aa36"}, {"pk": "b84d3375-0e09-4dd1-9809-f92d29d6aa36"} ] } # 转换为JSON字符串并指定content_type response = self.client.put( path, data=json.dumps(data), content_type="application/json" ) # 验证响应与数据库变更 self.assertEqual(response.status_code, 200) updated_task = Task.objects.get(pk=self.task.pk) # 由于两个pk相同,实际关联的TaskList数量为1 self.assertEqual(updated_task.tasklists.count(), 1)
通用测试嵌套Serializer的方法
可以从序列化输出、反序列化验证、视图请求三个层面进行测试:
1. 测试序列化输出
验证Serializer将模型实例转换为JSON结构是否符合预期:
def test_task_serializer_output(self): # 准备测试数据 test_list = TaskList.objects.create( pk="b84d3375-0e09-4dd1-9809-f92d29d6aa36", name="工作清单" ) test_task = Task.objects.create(title="完成文档") test_task.tasklists.add(test_list) # 序列化实例 serializer = TaskSerializer(test_task) # 断言输出结构 expected_data = { "title": "完成文档", "tasklists": [{"pk": "b84d3375-0e09-4dd1-9809-f92d29d6aa36"}] # 补充Serializer中定义的其他字段 } self.assertEqual(serializer.data, expected_data)
2. 测试反序列化验证
验证传入的JSON数据能被正确解析、验证并保存:
def test_task_serializer_deserialization(self): # 提前创建关联的TaskList test_list = TaskList.objects.create( pk="b84d3375-0e09-4dd1-9809-f92d29d6aa36", name="工作清单" ) # 构造符合格式的输入数据 input_data = { "title": "新任务", "tasklists": [{"pk": "b84d3375-0e09-4dd1-9809-f92d29d6aa36"}] } # 验证数据有效性并保存 serializer = TaskSerializer(data=input_data) self.assertTrue(serializer.is_valid()) saved_task = serializer.save() # 断言保存结果 self.assertEqual(saved_task.title, "新任务") self.assertIn(test_list, saved_task.tasklists.all())
3. 视图层集成测试
结合测试客户端发送真实请求,验证视图处理嵌套数据的逻辑是否正常:
def test_task_update_view(self): test_list = TaskList.objects.create( pk="b84d3375-0e09-4dd1-9809-f92d29d6aa36", name="工作清单" ) test_task = Task.objects.create(title="旧标题") path = test_task.get_absolute_api_url() # 构造更新数据并发送JSON请求 update_data = { "title": "更新后的标题", "tasklists": [{"pk": test_list.pk}] } response = self.client.put( path, json.dumps(update_data), content_type="application/json" ) # 断言响应与数据库状态 self.assertEqual(response.status_code, 200) updated_task = Task.objects.get(pk=test_task.pk) self.assertEqual(updated_task.title, "更新后的标题") self.assertEqual(updated_task.tasklists.first(), test_list)
内容的提问来源于stack exchange,提问作者Rauf Masoumi
相关产品推荐
相关产品推荐

