0

Tastypie が提供する API を使用した Django アプリがあり、すべてローカル サーバーとライブ サーバーで正常に動作しますが、特定の API を呼び出すテストを作成しようとするとエラーが発生します。

これは CURL リクエストです (Apache で実行されている私のローカル Django サーバーへ):

curl --dump-header - -H "Accept: application/json" -H "Content-Type: application/json" -H "Authorization: ApiKey user:025b513834656753db4bd7b32d66ea2e50ea08f3" -X POST --data '{"digest":"123456789123456789"}'  "http://localhost/python/api/v1/tracker/"

そして、これは(予想される)応答です:

HTTP/1.1 404 NOT FOUND
Date: Mon, 01 Jul 2013 18:15:53 GMT
Server: Apache/2.2.22 (Ubuntu)
Vary: Accept-Language,Cookie
Content-Language: en-us
Transfer-Encoding: chunked
Content-Type: application/json

{
    "error_message": "", 
    "traceback": "Traceback (most recent call last):\n\n  File \"/home/alex/data/development/home_alexlittle_net/venv/lib/python2.7/site-packages/tastypie/resources.py\", line 217, in wrapper\n    response = callback(request, *args, **kwargs)\n\n  File \"/home/alex/data/development/home_alexlittle_net/venv/lib/python2.7/site-packages/tastypie/resources.py\", line 459, in dispatch_list\n    return self.dispatch('list', request, **kwargs)\n\n  File \"/home/alex/data/development/home_alexlittle_net/venv/lib/python2.7/site-packages/tastypie/resources.py\", line 491, in dispatch\n    response = method(request, **kwargs)\n\n  File \"/home/alex/data/development/home_alexlittle_net/venv/lib/python2.7/site-packages/tastypie/resources.py\", line 1357, in post_list\n    updated_bundle = self.obj_create(bundle, **self.remove_api_resource_names(kwargs))\n\n  File \"/home/alex/data/development/home_alexlittle_net/venv/lib/python2.7/site-packages/tastypie/resources.py\", line 2150, in obj_create\n    return self.save(bundle)\n\n  File \"/home/alex/data/development/home_alexlittle_net/venv/lib/python2.7/site-packages/tastypie/resources.py\", line 2281, in save\n    self.is_valid(bundle)\n\n  File \"/home/alex/data/development/django-oppia/oppia/api/resources.py\", line 205, in is_valid\n    raise NotFound\n\nNotFound\n"

ただし、次のテスト リソース ケースを実行すると:

class TrackerResourceTest(ResourceTestCase): 
    fixtures = ['user.json', 'oppia.json']  

    def setUp(self):
        super(TrackerResourceTest, self).setUp()
        self.username = 'user'
        user = User.objects.get(username=self.username)
        api_key = ApiKey.objects.get(user = user)
        self.api_key = api_key.key
        self.url = '/api/v1/tracker/'

    def get_credentials(self):
        return self.create_apikey(username=self.username, api_key=self.api_key)

    def test_post_digest_not_found(self):
        data = {
            'digest': '123456789123456789',
        }
        resp = self.api_client.post(self.url, format='json', data=data, authentication=self.get_credentials())
        self.assertHttpNotFound(resp)

次のエラーが表示されます。

======================================================================
ERROR: test_post_digest_not_found (oppia.tests.TrackerResourceTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/alex/data/development/django-oppia/oppia/tests.py", line 459, in test_post_digest_not_found
    resp = self.api_client.post(self.url, format='json', data=data, authentication=self.get_credentials())
  File "/home/alex/data/development/home_alexlittle_net/venv/local/lib/python2.7/site-packages/tastypie/test.py", line 96, in post
    return self.client.post(uri, **kwargs)
  File "/home/alex/data/development/home_alexlittle_net/venv/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/test/client.py", line 463, in post
    response = super(Client, self).post(path, data=data, content_type=content_type, **extra)
  File "/home/alex/data/development/home_alexlittle_net/venv/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/test/client.py", line 297, in post
    return self.request(**r)
  File "/home/alex/data/development/home_alexlittle_net/venv/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/test/client.py", line 406, in request
    response = self.handler(environ)
  File "/home/alex/data/development/home_alexlittle_net/venv/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/test/client.py", line 111, in __call__
    response = self.get_response(request)
  File "/home/alex/data/development/home_alexlittle_net/venv/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/core/handlers/base.py", line 178, in get_response
    response = self.handle_uncaught_exception(request, resolver, sys.exc_info())
  File "/home/alex/data/development/home_alexlittle_net/venv/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/core/handlers/base.py", line 224, in handle_uncaught_exception
    return callback(request, **param_dict)
  File "/home/alex/data/development/home_alexlittle_net/venv/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/utils/decorators.py", line 91, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "/home/alex/data/development/home_alexlittle_net/venv/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/views/defaults.py", line 41, in server_error
    return http.HttpResponseServerError(template.render(Context({})))
  File "/home/alex/data/development/home_alexlittle_net/venv/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/template/base.py", line 140, in render
    return self._render(context)
  File "/home/alex/data/development/home_alexlittle_net/venv/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/test/utils.py", line 65, in instrumented_test_render
    return self.nodelist.render(context)
  File "/home/alex/data/development/home_alexlittle_net/venv/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/template/base.py", line 830, in render
    bit = self.render_node(node, context)
  File "/home/alex/data/development/home_alexlittle_net/venv/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/template/debug.py", line 74, in render_node
    return node.render(context)
  File "/home/alex/data/development/home_alexlittle_net/venv/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/template/loader_tags.py", line 124, in render
    return compiled_parent._render(context)
  File "/home/alex/data/development/home_alexlittle_net/venv/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/test/utils.py", line 65, in instrumented_test_render
    return self.nodelist.render(context)
  File "/home/alex/data/development/home_alexlittle_net/venv/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/template/base.py", line 830, in render
    bit = self.render_node(node, context)
  File "/home/alex/data/development/home_alexlittle_net/venv/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/template/debug.py", line 74, in render_node
    return node.render(context)
  File "/home/alex/data/development/home_alexlittle_net/venv/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/template/loader_tags.py", line 156, in render
    return self.render_template(self.template, context)
  File "/home/alex/data/development/home_alexlittle_net/venv/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/template/loader_tags.py", line 138, in render_template
    output = template.render(context)
  File "/home/alex/data/development/home_alexlittle_net/venv/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/template/base.py", line 140, in render
    return self._render(context)
  File "/home/alex/data/development/home_alexlittle_net/venv/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/test/utils.py", line 65, in instrumented_test_render
    return self.nodelist.render(context)
  File "/home/alex/data/development/home_alexlittle_net/venv/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/template/base.py", line 830, in render
    bit = self.render_node(node, context)
  File "/home/alex/data/development/home_alexlittle_net/venv/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/template/debug.py", line 74, in render_node
    return node.render(context)
  File "/home/alex/data/development/home_alexlittle_net/venv/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/templatetags/i18n.py", line 50, in render
    langs = self.languages.resolve(context)
  File "/home/alex/data/development/home_alexlittle_net/venv/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/template/base.py", line 728, in resolve
    value = self._resolve_lookup(context)
  File "/home/alex/data/development/home_alexlittle_net/venv/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/template/base.py", line 771, in _resolve_lookup
    (bit, current))  # missing attribute
VariableDoesNotExist: Failed lookup for key [LANGUAGES] in u"[{'False': False, 'None': None, 'True': True}, {}, {}]"

そのため、NotFound 例外が発生したという事実を認識していないようです。NotFound 例外は、API リソースの is_valid メソッドによって発生します。

def is_valid(self, bundle, request=None):
        exists = False
        try:
            activity = Activity.objects.get(digest=bundle.obj.digest)
            exists = True
        except Activity.DoesNotExist:
            pass

        try:
            media = Media.objects.get(digest=bundle.obj.digest)
            exists = True
        except Media.DoesNotExist:
            pass
        if not exists:
            raise NotFound()

このような不可解なエラー メッセージが表示される理由を理解するのに苦労しています。参考までに、DEBUG設定をTrueまたはFalseに設定しているかどうかに関係なく、ローカルサーバーのcurlリクエストから同じ応答を取得します(予想どおり)。

これが、テスト ケースまたは API リソースの記述方法に問題があるためかどうかはわかりません。

ヘルプ/ポインターは大歓迎です-テストを適切に機能させたいです。

4

1 に答える 1

0

私は今、どこで間違っていたのかを理解しました...私はいくつかの間違いを犯しました:

まず、is_valid は別の Validation クラスではなく、TrackerResource クラスのメソッドでした。これを独自の Validation クラスに移動し、これを TrackerResource で validation = TrackerValidation() として参照しました。

次に、is_valid が一連のエラー メッセージを返すのではなく、NotFound エラーを返すようにしました。これは、不正なデータが送信された場合に、404 Not Found ではなく 400 Bad Request のフラグを立てることを意味します。

私の TrackerValidation クラスは次のようになります。

class TrackerValidation(Validation):
    def is_valid(self, bundle, request=None):
        exists = False
        errors = {}
        try:
            activity = Activity.objects.get(digest=bundle.obj.digest)
            exists = True
        except Activity.DoesNotExist:
            pass

        try:
            media = Media.objects.get(digest=bundle.obj.digest)
            exists = True
        except Media.DoesNotExist:
            pass
        if not exists:
            errors['digest'] = [_(u'Digest not found')]
        return errors

これにより、ローカル サイトへの curl リクエストとテスト フレームワークの間で一貫した結果が得られるようになりました。

于 2013-07-02T08:03:34.363 に答える