Django Rest框架测试类错误

时间:2016-07-23 16:14:33

标签: django django-rest-framework

我收到这个奇怪的错误,我无法理解原因。我之前的项目中已经尝试过这种方法,但是使用Selenium比使用纯API测试用例更多的是在前端。

以下是代码:

from django.test import TestCase
from django.core.urlresolvers import reverse

from rest_framework import status
from rest_framework.test import APITestCase

from unittest import skip # This library is used to skip some class TestCase

from . models import *

import time # This library is used in case you want to put a sleep before proceeding to the next line of scripts
import inspect # This library is used to print the method of that certain class.. inspect.stack()[0][3]
import json # This library is for parsing the response.content

# Create your tests here.

url_1 = reverse('artists-list') # The URL endpoint for the artists which is /artists/ having POST and GET methods
url_2 = reverse('artists-detail', kwargs={'artist_id':1}) # The URL endpoint for the artists which is /artists/:d having GET, PUT and DELETE methods
url_3 = reverse('artists-detail', kwargs={'artist_id':3}) # Wrong id endpoint on purpose to check error response

# Check the response if there is no given data
class ArtistTestWithData(APITestCase):
    # indent is just used to specify the tab size
    # follow the json naming format
    # Command: python manage.py dumpdata store.artist --indent=2 > store/fixtures/artists_2016_07_23.json
    fixtures = ['artists_2016_07_23.json']

    # Check the response if there is a data within
    def test_get(self):
        # self.client attribute will be an APIClient instance
        # Basically it will act as a client
        response = self.client.get(url_1)
        data = json.loads(response.content)["data"]
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertNotEqual(len(data), 0) # There should be a data
        # print ("%s.%s DONE - 1" % (self.__class__.__name__, inspect.stack()[0][3]))

# Check the response if there is no given data
class ArtistTest(APITestCase):
    # For reusable of adding a single record
    # To be used for POST, GET(detailed), PUT and DELETE
    def _setup_add_record(self):
        _data = {"name": "50 Cent", "birth_date":"2005-02-13"}
        response = self.client.post(url_1, _data)
        data = json.loads(response.content)["data"]
        return ( response, _data, data )

    # Checks the records
    def test_get(self):
        # self.client attribute will be an APIClient instance
        # Basically it will act as a client
        response = self.client.get(url_1)
        self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
        self.assertEqual(response.content, '') # There should be no data
        # self.assertEqual(len(data), 0)
        # print ("%s.%s DONE - 1" % (self.__class__.__name__, inspect.stack()[0][3]))

    # Creates the record
    def test_post(self):
        x = self._setup_add_record()
        self.assertEqual(x[0].status_code, status.HTTP_201_CREATED) # Status 201 is the default when a new object is created 
        self.assertEqual(x[2], x[1]) # have the API return the updated (or created) representation as part of the response
        self.assertEqual(Artist.objects.count(), 1) # Make  sure that there is a craeted instance
        self.assertEqual(Artist.objects.get().name, '50 Cent') # Double checking if the last post is the created instance

    # Get a specific record
    def test_get_detail(self):
        x = self._setup_add_record()
        response = self.client.get(url_2)
        data = json.loads(response.content)["data"]
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(data, x[1])
        self.assertNotEqual(len(data), 0)

    # Update a specific record
    def test_put(self):
        x = self._setup_add_record()
        update = {"name": "60 Cents", "birth_date":"2005-02-13"}
        response = self.client.put(url_2, update)
        data = json.loads(response.content)["data"]
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertNotEqual(data, x[1])
        self.assertNotEqual(Artist.objects.get().name, '50 Cent') # Check if it is still the old name
        self.assertEqual(Artist.objects.get().name, '60 Cents') # Check the new name

    def test_delete(self):
        x = self._setup_add_record()
        response = self.client.delete(url_2)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        response = self.client.get(url_2)
        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)

# Check the response if there is error on requests
class ArtistTestErrors(APITestCase):
    def test_post(self):
        _data = {"birth_date":"2005-02-13"}
        response = self.client.post(url_1, _data)
        data = json.loads(response.content)["errors"] # checks the errors
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
        self.assertNotEqual(len(data), 0)

    def test_get_detail(self):
        ArtistTest._setup_add_record(self)
        response = self.client.get(url_3)
        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)

这是错误:

line 103, in test_get_detail
    ArtistTest._setup_add_record(self)
TypeError: unbound method _setup_add_record() must be called with ArtistTest instance as first argument (got ArtistTestErrors instance instead)

1 个答案:

答案 0 :(得分:1)

问题出在以下代码中:

def test_get_detail(self):
    ArtistTest._setup_add_record(self)
    response = self.client.get(url_3)
    self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)

您无法调用ArtistTest._setup_add_record之类的实例方法。您需要创建一个所有调用ArtistTest()._setup_add_record

之类的方法的实例

如果你想使用该方法是不同的类,那么去继承/混合:

class ArtistRecordSetupMixing():
    # For reusable of adding a single record
    # To be used for POST, GET(detailed), PUT and DELETE
    def _setup_add_record(self):
        _data = {"name": "50 Cent", "birth_date":"2005-02-13"}
        response = self.client.post(url_1, _data)
        data = json.loads(response.content)["data"]
        return ( response, _data, data )

在需要功能的测试用例中:

# Check the response if there is no given data
class ArtistTest(ArtistRecordSetupMixing, APITestCase):
    pass