我正在为一个用“login_required”装饰的视图做一些(隔离的)单元测试。例子:
@login_required
def my_view(request):
return HttpResponse('test')
是否可以测试“my_view”功能是否用“login_required”装饰?
我知道我可以使用集成测试(使用测试客户端)来测试行为(匿名用户被重定向到登录页面),但我想使用隔离测试来完成。
任何想法?
谢谢!
我正在为一个用“login_required”装饰的视图做一些(隔离的)单元测试。例子:
@login_required
def my_view(request):
return HttpResponse('test')
是否可以测试“my_view”功能是否用“login_required”装饰?
我知道我可以使用集成测试(使用测试客户端)来测试行为(匿名用户被重定向到登录页面),但我想使用隔离测试来完成。
任何想法?
谢谢!
当然,必须可以以某种方式对其进行测试。不过,这绝对不值得。编写一个完全隔离的单元测试来检查装饰器是否被应用只会导致一个非常复杂的测试。测试错误的可能性比测试行为错误的可能性要高得多。我强烈反对它。
测试它的最简单方法是使用 DjangoClient
伪造对关联 url 的请求,并检查重定向。如果你使用任何 Django 的测试用例作为你的基类:
class MyTestCase(django.test.TestCase):
def test_login_required(self):
response = self.client.get(reverse(my_view))
self.assertRedirects(response, reverse('login'))
一个稍微复杂但更孤立的测试是直接使用 RequestFactory 调用视图来创建请求对象。assertRedirects()
在这种情况下不起作用,因为它取决于设置的属性Client
:
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 的测试客户端检查正确的重定向。
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 -> assertion' 模式,而不是许多模拟框架使用的 'record -> replay'。
您将必须创建一个模拟对象。模拟对象在您访问它们时创建所有属性和方法,并存储它们如何使用的详细信息。您可以配置它们,指定返回值或限制可用的属性,然后断言它们的使用方式:
使用模拟对象的测试将仅测试my_view
函数是否用login_required
. 您不需要设置其他属性。
查看有关如何使用此链接使用模拟对象编写测试的文档。
此外,遵循 SO 链接可能有助于如何对装饰器进行猴子修补。
使用requests
库,如果您不向它传递身份验证 cookie,您可以根据它是否返回 401/403/200/whatever 来测试是否需要登录
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"