使用嵌套资源测试Django REST框架API响应

使用嵌套资源测试Django REST框架API响应

问题描述:

我正在为项目编写一个REST API并且菜单终端正在返回一个带有项目组的JSON,项目内部的项目可以将任何额外的用户添加到项目中。使用嵌套资源测试Django REST框架API响应

serializers.py 
==================== 
class ItemExtraSerializer(serializers.HyperlinkedModelSerializer): 

    class Meta: 
     model = ItemExtra 
     fields = ('id', 'name', 'price') 


class ItemSerializer(serializers.HyperlinkedModelSerializer): 
    extras = ItemExtraSerializer(many=True, read_only=True) 

    class Meta: 
     model = Item 
     fields = ('id', 'url', 'name', 'description', 'image', 'code', 'price', 'extras') 


class ItemGroupSerializer(serializers.HyperlinkedModelSerializer): 
    items = ItemSerializer(many=True, read_only=True) 

    class Meta: 
     model = ItemGroup 
     fields = ('id', 'url', 'name', 'items') 


views.py 
========================= 
class MenuView(ListAPIView): 
    serializer_class = ItemGroupSerializer 

    def get_queryset(self): 
     """ 
     Return the items inside their groups for search query 
     Filtering is one Group name and Item name 
     :return: 
     """ 
     queryset = ItemGroup.objects.all() 
     search_terms = self.request.query_params.get('q', None) 
     if search_terms: 
      queryset = Item.objects.search(search_terms) 
     return queryset 

tests.py 
======================== 

class ItemTestCases(APITestCase): 
    def setUp(self): 
     self.sandwich_group, created = ItemGroup.objects.get_or_create(name='Sandwiches') 
     self.meal_group, created = ItemGroup.objects.get_or_create(name='Meals') 
     self.shawarma_sandwich, created = Item.objects.get_or_create(name='Shawarma Sandwich', 
                    description='Meat Shawarma Sandwich', 
                    price=1.250, 
                    code='SW-01', 
                    group=self.sandwich_group) 
     self.burger_sandwich, created = Item.objects.get_or_create(name='Cheese Burger', 
                    description='Single cheese burger Sandwich', 
                    price=1.000, 
                    code='SW-02', 
                    group=self.sandwich_group) 
     self.burger_sandwich_extra, created = ItemExtra.objects.get_or_create(name='Extra cheese', 
                       price=0.100, 
                       item=self.burger_sandwich) 
     self.sharawma_meal, created = Item.objects.get_or_create(name='Shawarma Meal', 
                   description='Shawarma Sandwich with fries and drink', 
                   price=2.000, 
                   code='ME-01', 
                   group=self.meal_group) 
     self.burger_meal, created = Item.objects.get_or_create(name='Burger Meal', 
                   description='Single cheese burger Sandwich', 
                   price=2.250, 
                   code='ME-02', 
                   group=self.meal_group) 
     self.cheese_meal_extra, created = ItemExtra.objects.get_or_create(name='Extra cheese', 
                      price=0.100, 
                      item=self.burger_meal) 
     self.factory = APIRequestFactory() 



    def test_menu_GET_request(self): 
     item_list = reverse('menu') 
     response = self.client.get(item_list) 
     self.assertEqual(response.status_code, status.HTTP_200_OK) 
     groups = ItemGroup.objects.all() 
     expected = ItemGroupSerializer(groups) 
     self.assertContains(response, expected.data) 

测试的输出是:

的AssertionError:HyperlinkedIdentityField需要在串行器上下文的请求。实例化串行器时添加context={'request': request}

如何将serlizer渲染为JSON以便将其与API端点JSON进行比较?

更新1: 我看着办吧,但我觉得有一个清晰的解决方案

我创建的辅助功能

def render_many_serializer_as_json(serializer, request, instance): 
    serializer_data = serializer(instance=instance, many=True, context={'request': request}).data 
    return JSONRenderer().render(serializer_data) 

和重写我的测试

def test_menu_GET_request(self): 
     item_list = reverse('menu') 
     request = self.factory.get(item_list, format='json') 
     response = self.client.get(item_list) 
     groups = ItemGroup.objects.all() 
     expected = render_many_serializer_as_json(ItemGroupSerializer, request, groups) 
     self.assertEqual(response.content, expected) 

为什么要做些复杂的事 就明确地写下来预期JSON输出:

expected = { 
    'id': 1, 
    'name': ..., 
    ..., 
    'items': [{ 
     'id': .., 
     'url': ..., 
    }] 
} 
+0

因为如果我改变了串行结构,在这种情况下,我想改变测试的欢迎,并写了这样大的JSON的是头痛。 –

+0

而且你将无法保证你的界面合同,因为如果序列化器发生变化,你的界面将会被忽略。 – Linovia