【问题标题】:Django REST Framework - Set request in serializer test for ApiClientDjango REST Framework - 在 ApiClient 的序列化程序测试中设置请求
【发布时间】:2020-05-23 04:07:19
【问题描述】:

我已经阅读:Django REST Framework - Set request in serializer test?。它对我不起作用!因为我使用的是 APIClient 而不是像他这样的 RequestFactory。

我构建了一个使用 Django REST 框架实现后端的 Web 应用程序。现在我正在编写单元测试,我在测试我的序列化方法时遇到了一个问题。这是我正在努力解决的序列化程序方法的一个示例:

def get_can_edit(self, obj):
  request = self.context['request']
  user = User.objects.get(username=request.user)
  return user == obj.admin

当试图从测试中调用它时,首先我声明了一个序列化器的实例:

但是现在我需要 self.serializer 在 get_can_edit 执行 self.context.get('request') 时获得正确的请求。我使用 APIClient 创建了一个包含正确信息的虚假请求:

self.client = APIClient()
self.client.force_authenticate(user)
conference = a_fake_conference

res = self.client.get('conference:conference-detail'. args=[conference.id])
serializer = ConferenceSerializer(conference, context={WHAT_IS_REQUEST?}) 
# I'm using a dict as context but the request gave me an error: context={'request': { 'user': user }}

sert.assertEqual(res.data, serializer.data)

现在我被卡住了,因为我不确定如何将 request1 添加到序列化程序以便 request = self.context['request'] 将返回

谢谢。

【问题讨论】:

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


    【解决方案1】:

    使用APIClientwsgi_request (source code-Django)获取WSGI请求对象。

    self.client = APIClient()
    self.client.force_authenticate(user)
    res = self.client.get('conference:conference-detail'. args=[conference.id]
    # make sure to call the `get(...)` method before accessing `wsgi_request` attribute
    request_object = res.wsgi_request

    免责声明:不确定这是否是获取 request 对象的 DRF 方式。

    【讨论】:

    • 太棒了。但是,基于代码:github.com/encode/django-rest-framework/blob/master/…wsgi_request 不存在。但是,请求存在。所以,我尝试使用self.client.request(),它回答它是一个字典,所以最后我尝试了self.client.request,它返回类似:{'PATH_INFO': '/api/survey/', 'REQUEST_METHOD': 'GET', 'SERVER_PORT': '80', 'wsgi.url_scheme': 'http', 'QUERY_STRING': '', 'CONTENT_TYPE': 'application/octet-stream'} 它没有解决我的问题(因为没有用户)但它很棒线索!谢谢!
    • 我添加了wsgi_request 参考(检查更新的答案)
    • 我的错!让我检查一下!
    • 您应该访问 self.client.wsgi_request 而不是 self.client.request
    • 我建议你稍微更新一下:self.client.wsgi_request 给出下一个错误:AttributeError: 'APIClient' object has no attribute 'wsgi_request' 为什么?因为它是获取后使用的客户端的属性。所以,在我的代码中:就像:res = self.client.get('conference:conference-detail'. args=[conference.id]) res.wsgi_request 你可以试试!但它解决了我的问题,检查res.wsgi_request 而不是客户端。非常感谢!如果你改变它,我会很高兴作为接受的答案!
    【解决方案2】:

    你在这里测试了两个东西,所以这是问题的一部分。通常,您会将self.client.get(...) 用作集成测试,即确保从请求到响应的所有内容都按预期工作的测试。对于这样的测试,您不会使用序列化程序,因为您使用的是应用程序代码(您的序列化程序)来测试自身。

    如果您正在编写集成测试,您应该使用以下内容测试原始响应:

    from django.test import TestCase, RequestFactory
    
    class MyUnitTestCase(TestCase):
        def test_the_whole_stack(self):
            response = self.client.get(
                "conference:conference-detail", args=[conference.id]
            )
            self.assertEqual(response.status_code, 200)
            self.assertEqual(
                response.json()["some-key-you-expect"],
                "Some value you expect"
            )
    

    请注意,您也不必直接调用 APIClient()。默认情况下它就在那里。

    对于单元测试,就像您为确保序列化程序正常工作而编写的那种测试一样,您不需要或不想使用 WSGIRequest 对象。相反,Django 为这种情况提供了一个 RequestFactory:

    from django.test import TestCase, RequestFactory
    
    class MyUnitTestCase(TestCase):
        def test_my_serialiser(self):
            serializer = ConferenceSerializer(
                conference,
                context={"request": RequestFactory().get("/")}
            )
            self.assertEqual(
                serialiser.data["some-key-you-expect"],
                "Some value you expect"
            )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-04
      • 2020-08-04
      • 2019-01-19
      • 1970-01-01
      • 2015-08-08
      • 1970-01-01
      • 2018-12-15
      • 1970-01-01
      相关资源
      最近更新 更多