2016-05-12 144 views
0

我正在爲項目編寫一個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) 

回答

0

爲什麼要做些複雜的事 就明確地寫下來預期JSON輸出:

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

因爲如果我改變了串行結構,在這種情況下,我想改變測試的歡迎,並寫了這樣大的JSON的是頭痛。 –

+0

而且你將無法保證你的界面合同,因爲如果序列化器發生變化,你的界面將會被忽略。 – Linovia