Django SECURE_SSL_REDIRECT打破使用内置客户端

时间:2018-04-03 09:41:56

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

我正在开发一个已经有数百个单元测试的项目,其中许多使用内置的django客户端或django rest框架APIClient来发出请求和测试响应。

最近已实施必要条件以使SSL在本地工作,并将SECURE_SSL_REDIRECT设置为True(尝试使我们的dockerised devtest环境接近production因为可能),我找到了一个裁剪器,发现很多单元测试都失败了,因为(API)客户端默认情况下请求使用http,而不是https。

许多(大多数)请求看起来像这样:

response = self.client.get(some_url)

我知道我可以使用:

response = self.client.get(some_url, secure=True)

但这确实意味着改变很多的单元测试。使用follow=True也是如此,但有一个额外的缺点,即这会产生一些其他不良行为。

我无法看到将安全请求的使用设置为Django Client中的默认行为的方法。我可以创建自己的SecureClient(和SecureAPIClient),但我必须确保我创建一个新的基础TestCase(可能是多个)来继承,并在所有测试的每个地方进行更改 - 仍然需要做很多工作。 / p>

当然可以对客户端进行修补,但我不愿意这样做,因为它可能会产生以后难以调试的不良影响。

TLDR;是否有一种简单(理想支持)的方式,通过django测试的客户端进行所有单元测试请求,默认情况下使用SSL?

3 个答案:

答案 0 :(得分:3)

  • 选项1.需要时禁用SECURE_SSL_REDIRECT

    from django.test import override_settings
    
    class FooTest(TestCase):
    
        def setUp(self):
            settings_manager = override_settings(SECURE_SSL_REDIRECT=False)
            settings_manager.enable()
            self.addCleanup(settings_manager.disable)
    
  • 选项2:包裹get的{​​{1}}和post方法:

    APIClient
  • 选项3:只为未设置class ApiTestCase(TestCase): def setUp(self): self.client = APIClient() def get(self, *args, **kwargs): return self.client.get(secure=True, *args, **kwargs) def post(self, *args, **kwargs): return self.client.post(secure=True, *args, **kwargs) 的测试环境维护单独的设置文件。

我已经尝试了所有三个选项并建议使用(3)。原因如下:

  1. SECURE_SSL_REDIRECT只是对真实客户的模仿。它可以对您的观点进行单元测试。它不会产生真正的WSGI请求,因此测试环境无论如何都不会匹配生产环境。

  2. django.test.clientSECURE_SSL_REDIRECT设置。 Don't unit test third-party code

  3. 确保您的代码始终使用SSL是一个很好的目标。但是,这是集成测试问题。这项工作的正确工具是Selenium + LiveServerTestCase

答案 1 :(得分:1)

如果您使用的是pytestpytest-django,则还可以制作修改测试客户端的设备:

import functools
import pytest

@pytest.fixture
def client(client):
    client.get = functools.partial(client.get, secure=True)
    client.post = functools.partial(client.post, secure=True)
    return client

答案 2 :(得分:0)

这是一个有趣的问题,我在不更改现有单元测试的情况下解决它的方法是修改 manage.py 以在运行测试时设置 SECURE_SSL_REDIRECT = False

您可以简单地导入

from django.conf import settings

在 manage.py 并添加

    # Disable HTTPS redirects while testing with Django's HTTP test client.
    if len(sys.argv) > 1 and sys.argv[1] == "test":
        settings.SECURE_SSL_REDIRECT = False

之前

execute_from_command_line(sys.argv)