在Django测试中通过模拟绕过装饰器

时间:2018-10-11 19:43:16

标签: django unit-testing mocking

我试图编写一个简单的测试,但是我的视图用嵌套的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):
    ...

以上内容仍然无法通过装饰器。

谢谢!

1 个答案:

答案 0 :(得分:0)

这种用装饰器进行修补的方法很可能不起作用,因为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中。