【问题标题】:Bypass decorator with mock in django test在 django 测试中使用 mock 绕过装饰器
【发布时间】:2018-10-11 19:43:16
【问题描述】:

我正在尝试编写一个简单的测试,但是我的视图用嵌套的 user_passes_test 语句装饰。他们检查诸如条带订阅和 is_authenticated 之类的内容。我发现了各种帖子,例如this,其中解决了如何绕过带有补丁的装饰器,但我不太清楚如何将所有东西集成在一起。

tests.py

@patch('dashboard.views.authorised_base_user_checks', lambda func: func)
def test_dashboard_root_exists(self):
    response = self.client.get('/dashboard/')
    self.assertEqual(200, response.status_code)

视图中的装饰器

def authorised_base_user_checks(view_func):
    decorated_view_func = login_required(user_active(subscriber_exists(subscriber_valid(view_func))))
    return decorated_view_func

views.py

@authorised_base_user_checks
def IndexView(request):
    ...

上面还是没有通过装饰器。

谢谢!

【问题讨论】:

    标签: django unit-testing mocking


    【解决方案1】:

    这种修补装饰器的方法很可能不起作用,因为views 模块的导入发生在修补之后。如果 view 已经被导入,那么装饰器已经被应用到 IndexView 并且修补装饰器功能将完全没有效果。

    您可以重新加载视图模块来克服这个问题:

    import imp
    import dashboard.views
    
    @patch('dashboard.views.authorised_base_user_checks', lambda func: func)
    def test_dashboard_root_exists(self):
       # reload module to make sure view is decorated with patched decorator
       imp.reload(views)
    
       response = self.client.get('/dashboard/')
       self.assertEqual(200, response.status_code)
    
       # reload again
       patch.stopall()
       imp.reload(views)
    

    免责声明:此代码仅演示该想法。您需要确保stopall 和最终重新加载总是发生,所以它们应该在finallytearDown 中。

    【讨论】:

    • 那里的代码给出了这个想法,我还没有运行它等等。最后一个patch 的函数名称不正确。我现在修好了
    • 谢谢,我用这些更改更新了我的……如果仍在调用装饰器,堆栈跟踪是您所期望的吗?还是可能有所不同?
    • 刚刚检查,def authorised_base_user_checks(view_func): 代码实际上并没有被调用,因为我在其中放置了一个设置跟踪但它没有被激活
    • 抱歉,我对模拟装饰器内部的想法具有误导性,因为它在这种情况下不起作用(即因为装饰器中没有实际的函数调用,它使用其他函数来包装)。
    • 没问题,感谢您的尝试...不幸的是,上述方法仍然失败,我想嵌套会使事情变得复杂,我必须多看看。感谢您的帮助
    猜你喜欢
    • 2018-09-22
    • 2017-05-03
    • 1970-01-01
    • 2012-02-14
    • 1970-01-01
    • 1970-01-01
    • 2012-11-01
    • 2012-08-23
    • 1970-01-01
    相关资源
    最近更新 更多