【问题标题】:Django Rest Framework test fails: Expected view to be called with a URL keyword argumentDjango Rest Framework 测试失败:使用 URL 关键字参数调用预期视图
【发布时间】:2016-11-27 18:37:05
【问题描述】:

我正在使用 Django Rest 框架编写的 UserDetail 视图上运行测试。

urls.py

    url(r'^api/users/', include('calorie_counter.users.urls', namespace='users')),

users/urls.py

    url(r'^(?P<pk>[0-9]+)$', views.UserDetail.as_view(), name='user-detail'),

test_api.py

BaseAPITestCase(APITestCase):
    def setUp(self):
        self.superuser = User.objects.create_superuser('admin', 'admin@test.com', 'johnpassword')
        self.client.login(username='john', password='johnpassword')
        self.user1 = User.objects.create(username="user1", password="pass", email="user1@test.com")


class ReadUserTest(BaseAPITestCase):
# check read permissions
    def test_user_can_read_self_detail(self):
        url = '/api/users/'+str(self.user1.id)
        factory = APIRequestFactory()
        request = factory.get(url)
        force_authenticate(request, self.user1)
        response = (UserDetail.as_view())(request)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

但是,运行此测试时出现以下错误。 'pk' 参数未传递到 UserDetail 视图。

AssertionError: Expected view UserDetail to be called with a URL keyword argument named "pk". Fix your URL conf, or set the .lookup_field attribute on the view correctly.

如何使用 URL 参数测试视图?

更新:

现在使用 APIClient 而不是工厂..

def test_user_can_read_self_detail(self):
    client = APIClient()
    client.login(username='user1', password='pass')

    # response = self.client.get('/api/users/', {'pk': self.user.id})
    response = client.get('/api/users/' + str(self.user1.id))
    self.assertEqual(response.status_code, status.HTTP_200_OK)

现在我收到以下错误:

AttributeError: 'AnonymousUser' object has no attribute 'is_manager'

manager 在哪里是我的自定义用户模型的一个属性。我猜客户端身份验证存在一些问题。我启用了会话身份验证。仍然出现此错误。

更新:我的登录不适用于 APICLient,因为我使用 User.objects.create 而不是 User.objects.create_user 创建用户。改变它解决了这个问题。 :)

【问题讨论】:

    标签: django testing django-rest-framework django-testing


    【解决方案1】:

    我认为您不需要进行所有这些设置,需要自己实例化视图类是不寻常的 - 也许您会通过以下方式利用测试客户端获得更多成功:

    def test_user_can_read_self_detail(self):
        url = reverse('api:user-detail', kwargs={'pk': self.user.id})
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
    

    如果您在身份验证方面遇到问题,我怀疑这可能是导致您来到这里的原因,您可能想尝试一下:

    self.client.login(username='example', password='changeme')
    

    import base64
    self.client.defaults['HTTP_AUTHORIZATION'] = 'Basic ' + base64.b64encode('example:changeme')
    

    我过去曾使用这两种方法来测试经过身份验证的 API 端点。

    【讨论】:

    • 我在 reverse() 中遇到错误。我正在使用反向('用户:用户详细信息')。我收到错误:字典更新序列元素 #0 的长度为 1; 2 是必需的
    • 我通过将 user_id 附加到 URL 来修复该部分。现在我收到身份验证错误,`AttributeError: 'AnonymousUser' object has no attribute 'is_manager'` 即使在使用客户端和身份验证凭据之后,我的测试也启用了会话身份验证。
    • 我认为我没有足够的信息来诊断——但关于你所说的关于身份验证的内容——请记住,DRF 的身份验证系统完全独立于 Django 的——而 Django 前端可以通过session auth,你几乎肯定想在 API 上使用 basic/token/oauth,并且可能没有为 DRF 验证正确的方式——我测试使用后一个 auth 标头来消除任何歧义。
    • 哦,我的错 - 在我的示例中,我从 POST 请求中提取了相反的内容 - 我已经更新了它 - tl;dr 你想传递 GET 参数到kwargs kwarg 到reverse 不作为.get 的第二个参数(.post 中的第二个参数用于请求正文数据)
    • @Ajax 全部排序?如果是,请接受这个答案:-)
    猜你喜欢
    • 2018-10-10
    • 2017-06-07
    • 2018-08-17
    • 1970-01-01
    • 2014-07-23
    • 1970-01-01
    • 1970-01-01
    • 2020-06-07
    • 2011-02-11
    相关资源
    最近更新 更多