Django SECURE_SSL_REDIRECT破坏使用内置客户端的单元测试

Dav*_*nes 5 django ssl unit-testing django-rest-framework

我正在一个已经有数百个单元测试的项目中,其中许多使用内置的django Client或django rest框架APIClient进行请求和测试响应。

最近刚刚实施的必要性,使SSL工作在本地,并设置SECURE_SSL_REDIRECT为True(试图让我们的dockerised devtest环境接近production可能),我有栽跟头发现如此多的单元测试失败,由于(API客户端默认情况下始终使用http而不是https进行请求。

许多(大多数)请求如下所示:

response = self.client.get(some_url)
Run Code Online (Sandbox Code Playgroud)

我知道我可以使用:

response = self.client.get(some_url, secure=True)
Run Code Online (Sandbox Code Playgroud)

但这确实意味着要更改许多单元测试。使用时也是如此follow=True,但是还具有其他缺点,即这可能会产生其他一些不良行为。

我看不到在Django客户端中将安全请求的使用设置为默认行为的方法。我可以创建自己的SecureClient(和SecureAPIClient),但随后必须确保创建一个新的基本TestCase(可能是多个)来继承,并在所有测试中都对其进行更改-仍然很多工作。

当然可以猴子修补客户端,但是我不愿意这样做,因为它可能会产生不良后果,以后很难调试。

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

Max*_*ysh 5

  • 选项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)
    
    Run Code Online (Sandbox Code Playgroud)
  • 选项2:的包装getpost方法APIClient

    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)
    
    Run Code Online (Sandbox Code Playgroud)
  • 选项3:只为测试环境维护一个单独的设置文件,SECURE_SSL_REDIRECT而未设置。

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

  1. django.test.client只是对真实客户的模仿。在这里可以对您的视图进行单元测试。它不会产生真正的WSGI请求,因此测试环境无论如何都不会与生产环境匹配。

  2. SECURE_SSL_REDIRECT是一个SecurityMiddleware设置。不要对第三方代码进行单元测试

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