当我遇到这个有趣的困境时,我正在为Django应用程序进行一些代码覆盖率单元测试。
class TestLogin(TestCase):
def setUp(self):
self.client = Client()
self.url = reverse('account:login')
self.template = 'account/login.html'
# This test works
def test_POST_invalid_login(self):
response = self.client.post(self.url, {
'username': 'foo',
'password': 'bar'
})
self.assertEqual(response.status_code, 401)
self.assertTemplateUsed(response, self.template)
# This is not working as intended.
def test_POST_no_data(self):
with self.assertRaises(MultiValueDictKeyError):
self.client.post(self.url, None)
class Login(View):
form_class = LoginForm
template = 'account/login.html'
def get(self, request):
form = self.form_class(None)
context = {
'form': form
}
return render(request, self.template, context)
def post(self, request):
try:
# Retrieve the username and password
username = request.POST['username']
password = request.POST['password']
# Create a user object from authentication, or return None
user = authenticate(username=username, password=password)
# Check if user was created
if user is not None:
# Login the user to the website
login(request, user)
messages.success(request, 'Login successful! Welcome ' + user.first_name + ' ' + user.last_name)
# Eventually have this go to profile pages.
return redirect('home', permanent=True)
else:
messages.error(request, 'Login failed: Invalid User.')
except MultiValueDictKeyError:
messages.error(request, 'Login failed: Invalid User.')
# Clear the form since the login attempt failed.
form = self.form_class(None)
context = {
'form': form
}
return render(request, self.template, context, status=401)
第一个测试test_POST_invalid_login
会像预期的那样发送数据,但是第二个测试test_POST_no_data
不应发送任何数据,但是视图仍然可以识别foo
和{ {1}}用户名和密码值因此无法捕获异常。我最初是先编写 no data 测试,然后才开始工作。我尝试将测试方法移至无效登录测试上方,但该方法仍然会失败。
有什么建议吗?
答案 0 :(得分:2)
您的test_POST_no_data
测试断言MultiValueDictKeyError
被引发,但是视图中捕获了此异常,因此视图将永远不会引发它。因此,test_POST_no_data
应该类似于test_POST_invalid_login
,即应该声明相同的内容。
您可以通过在raise
块中写入空的except MultiValueDictKeyError:
语句来检查是否为真。这样,您将重新引发相同的异常,并且测试将通过。
答案 1 :(得分:0)
由于我想在代码中捕获异常;我决定重构 no data 测试来检查它是否会得到以下断言。当然,我可以删除try / except块,并检查request.POST
是否具有以下键:username
和password
,但是我希望它正常运行并让应用返回带有失败消息的登录页面,而不是带有单元测试的轮廓。
# Refactored, and working
def test_POST_no_data(self):
self.assertEqual(response.status_code, 401)
self.assertTemplateUsed(response, self.template)
如果这是处理异常和测试异常的最佳方法,我可能会提出另一个问题,但这将是另一个问题。
谢谢Iulia Chiriac。