How to test if a view is decorated with “login_required” (Django)
我正在为一个用"login_required"装饰的视图做一些(隔离的)单元测试。 例:
1 2 3 | @login_required def my_view(request): return HttpResponse('test') |
是否可以测试"my_view"函数是否用"login_required"修饰?
我知道我可以通过集成测试(使用测试客户端)来测试行为(匿名用户被重定向到登录页面),但我想通过隔离测试来完成。
任何的想法?
谢谢!
当然,必须有可能以某种方式测试它。不过,这绝对不值得。编写完全隔离的单元测试来检查装饰器是否应用只会导致非常复杂的测试。测试错误的可能性高于测试行为错误的可能性。我强烈反对它。
测试它的最简单方法是使用Django的
1 2 3 4 | class MyTestCase(django.test.TestCase): def test_login_required(self): response = self.client.get(reverse(my_view)) self.assertRedirects(response, reverse('login')) |
稍微复杂但稍微孤立的测试是使用RequestFactory直接调用视图来创建请求对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | from django.test.client import RequestFactory class MyTestCase(django.test.TestCase): @classmethod def setUpClass(cls): super(MyTestCase, cls).setUpClass() self.rf = RequestFactory() def test_login_required(self): request = self.rf.get('/path/to/view') response = my_view(request, *args, **kwargs) self.assertEqual(response.status_code, 302) self.assertEqual(response['Location'], login_url) ... |
在用户登录和未登录时,使用Django的测试客户端检查是否有正确的重定向。
1 2 3 4 5 6 7 8 9 10 11 12 13 | from django.test import TestCase from django.core.urlresolvers import reverse class TestLoginRequired(django.test.TestCase): def test_redirects_to_login_page_on_not_loggedin(self): response = self.client.get(reverse(my_view)) self.assertRedirects(response, reverse('login_page')) def test_redirects_to_test_page_on_loggedin(self): self.client.login(username='my_username', password='my_password') response = self.client.get(reverse(my_view)) self.assertRedirects(response, reverse('test')) |
MOCK图书馆:
对于隔离测试或"纯"单元测试,您可以使用
Mock是一个用于Python测试的库。它允许您使用模拟对象替换受测试系统的部分,并对如何使用它们进行断言。
Mock基于'action - >断言'模式,而不是许多模拟框架使用的'record - > replay'。
您将不得不创建一个模拟对象。模拟对象在您访问它们时会创建所有属性和方法,并存储它们的使用方式的详细信息。您可以配置它们,指定返回值或限制可用的属性,然后对它们的使用方式进行断言:
使用模拟对象的测试将仅测试
查看有关如何使用此链接使用模拟对象编写测试的文档。
此外,遵循SO链接可能有助于如何猴子修补装饰器。
- 我怎样才能在测试时对Django模型中的装饰器进行猴子修补?
- 我可以在包装函数之前修补Python装饰器吗?
使用
1 2 3 4 5 6 | import requests req = requests.get("http://yoururl.com") if req.status_code ==200: print"login not needed apparently" else: print"check for other status codes or redirect" |