Django SECURE_SSL_REDIRECT破坏使用内置客户端的单元测试 [英] Django SECURE_SSL_REDIRECT breaks unit tests that use the in-built client

查看:190
本文介绍了Django SECURE_SSL_REDIRECT破坏使用内置客户端的单元测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



最近已实现了使SSL在本地运行的必要条件,并将 SECURE_SSL_REDIRECT 设置为True(试图使我们的dockerized dev test 环境与 possible 尽可能接近生产),我来找茬了,发现这么多单元测试失败了,这是由于(API)客户端默认情况下始终要求使用HTTP而不是https。



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

  response = self.client.get(some_url)

我知道我可以使用:

 响应= self.client.get(some_url,secure = True)

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



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

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

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

解决方案


  • 选项1。在需要时禁用 SECURE_SSL_REDIRECT



    <$ p来自django.test的$ p> 导入override_settings

    类FooTest(TestCase):

    def setUp(self):
    settings_manager = override_settings (SECURE_SSL_REDIRECT = False)
    settings_manager.enable()
    self.addCleanup(settings_manager.disable)


  • 选项2:包装 get post 方法APIClient

      class ApiTestCase(TestCase):
    def setUp(self):
    self.client = APIClient()

    def get(self,* args,** kwargs):
    返回self.client.get(secure = True,* args,* * kwargs)

    def post(self,* args,** kwargs):
    return self.cl ient.post(secure = True,* args,** kwargs)


  • 选项3:只需为测试环境维护一个单独的设置文件,而未设置 SECURE_SSL_REDIRECT




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


  1. django.test.client 只是一个模仿真正的客户。它可以对您的视图进行单元测试。它不会产生真正的WSGI请求,因此测试环境始终无法与生产环境匹配。


  2. SECURE_SSL_REDIRECT SecurityMiddleware 设置。 请勿对第三方代码进行单元测试


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



I am working on a project that already has hundreds of unit tests, many of which use either the built in django Client, or the django rest framework APIClient for making requests and testing responses.

Having recently implemented the necessaries to make SSL work locally, and setting the SECURE_SSL_REDIRECT to True (trying to make our dockerised dev and test environments as close to production as possible), I have come a cropper to find that so many unit tests fail, due to the (API)Clients requesting, by default, always using http, not https.

Many (most) requests look like this:

response = self.client.get(some_url)

I am aware that I could use:

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

But this does mean changing a lot of unit tests. The same is true for using follow=True, but had the added disadvantage that this could produce some other undesired behaviour.

I cannot see a way of setting the use of secure requests as a default behaviour in the Django Client. I could make my own SecureClient (and SecureAPIClient), but I would then have to make sure that I make a new base TestCase (possibly multiple) to inherit from, and change this everywhere for all the tests - still a lot of work.

It is possible of course to monkey patch the Client, but I am reluctant to to do this as, again, it could have undesired effects that are hard to debug later.

TLDR; Is there a simple (ideally supported) way, to make all unit test requests via the django test's Client, to use SSL by default?

解决方案

  • Option 1. Disable the SECURE_SSL_REDIRECT when needed:

    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)
    

  • Option 2: Wrap get and post methods of the 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)
    

  • Option 3: just maintain a separate settings file for the test environment with the SECURE_SSL_REDIRECT not being set.

I've tried all three options and recommend going with the (3). Here is why:

  1. django.test.client is just an imitation of a real client. It's there to unit test your views. It doesn't produce real WSGI requests, so test environment won't match production environment anyway.

  2. SECURE_SSL_REDIRECT is a SecurityMiddleware setting. Don't unit test third-party code.

  3. Making sure that your code always uses SSL is a good goal. However, this is an integration testing problem. The right tool for this job is Selenium + LiveServerTestCase.

这篇关于Django SECURE_SSL_REDIRECT破坏使用内置客户端的单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆