我有一个使用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异常的事实。我的API资源is_valid方法引发了NotFound异常:
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()
我正在努力弄清楚为什么我会收到如此神秘的错误消息 - 似乎是在看Django模板(?),但由于这是使用TastyPie API,因此应用程序的这一部分不使用模板。有关信息,我从本地服务器上的curl请求获得相同的响应,无论我将DEBUG设置设置为True还是False(正如我所期望的那样)。
我不清楚这是因为我编写测试用例或API资源的方式有问题吗?
任何帮助/指针都非常感激 - 我真的很想让测试正常运行。
答案 0 :(得分:0)
我现在已经弄清楚我哪里出错......我犯了几个错误:
首先,is_valid不在单独的Validation类中,它是TrackerResource类的一个方法。我现在已将其移至其自己的Validation类中,并在我的TrackerResource中将其引用为validation = TrackerValidation()。
其次,我让is_valid返回NotFound错误,而不是允许它返回一组错误消息 - 这意味着如果发送了错误数据,它会标记400 Bad Request,而不是404 Not Found。
我的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请求结果。