如何解决有没有更好的方法来比较Django模型数据和Django REST Framework响应数据?
我正在使用Django REST Framework构建API。我发现自己编写了很多重复的代码来测试API视图,所以我决定尝试编写一个mixin类,可以将其添加到测试用例中,以减少花在重复测试上的时间。
一个真正常见的测试是API响应数据与存储在数据库中的对象完全匹配。例如,一个测试可能看起来像这样:
def test_list_object_response_returns_correct_json_data(self):
objects = Object.objects.all()
response = self.client.get(reverse('object-list'))
response_json = response.json()
for num,obj in enumerate(response_json):
# convert JSON date strings to datetime objects
obj_created = self.json_date_string_to_datetime(obj['created'])
obj_updated = self.json_date_string_to_datetime(obj['updated'])
self.assertEqual(obj['object_id'],str(objects[num].object_id))
self.assertEqual(obj['name'],objects[num].name)
self.assertEqual(obj_created,objects[num].created)
self.assertEqual(obj_updated,objects[num].updated)
这通过了,所以我发现自己经常使用这种模式来比较GET响应与数据库中存储的所有对象是否匹配。
我了解到,推广这种模式很复杂。到目前为止,这是我想出的一个mixin(在正面和负面测试用例中也都通过了测试):
class GetMixin(BaseMixin):
# BaseMixin has some more general methods that help with API tests
# regardless of HTTP request method
@classmethod
def response_and_model_data_are_equal(cls,response,model):
# first,verify that model is a Django model for .objects.all()
if isinstance(model,ModelBase):
instances = model.objects.all()
# then,verify that the response data is a list rather than
# a single item (e.g. a dict)
if isinstance(response.data,list):
# Assume the data match until they don't
data_match = True
for num,item in enumerate(response.data):
for field in cls.get_fields(item):
# if a datetime field comes up,convert the JSON
# timestamp string into a python datetime object
if isinstance(getattr(instances[num],field),datetime):
item_field_data = cls.json_date_string_to_datetime(item[field])
else:
item_field_data = item[field]
if item_field_data != getattr(instances[num],field):
data_match = False
return data_match
else:
return False
else:
return False
这感觉不必要地凌乱并且难以维护。有没有更优雅的方式来概括这种比较?
可能值得注意的是,我最终还是想使用相同的方法将包含单个项目的响应与模型实例进行比较,以便无论是否传递列表/模型组合或项目/实例组合。
更新...
经过几个不同的测试用例后,这就是我要去的地方。我最终创建了一个TestSerializer
,它可以接受任何任意模型来帮助清理问题。
@classmethod
def response_and_model_data_are_equal(cls,object_data_source):
if isinstance(object_data_source,ModelBase):
serializer_data = []
instances = object_data_source.objects.all()
for instance in instances:
serializer = TestSerializer(instance,model=object_data_source)
serializer_data.append(serializer.data)
else:
serializer = TestSerializer(object_data_source,model=type(object_data_source))
serializer_data = serializer.data
return response.data == serializer_data
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。