Django-测试携带POST变量

时间:2019-10-22 12:48:58

标签: python django unit-testing django-unittest

当我遇到这个有趣的困境时,我正在为Django应用程序进行一些代码覆盖率单元测试。

tests / test_views.py

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)

views.py

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 测试,然后才开始工作。我尝试将测试方法移至无效登录测试上方,但该方法仍然会失败。

有什么建议吗?

2 个答案:

答案 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是否具有以下键:usernamepassword,但是我希望它正常运行并让应用返回带有失败消息的登录页面,而不是带有单元测试的轮廓。

tests / test_view.py

# Refactored, and working
def test_POST_no_data(self):
    self.assertEqual(response.status_code, 401)
    self.assertTemplateUsed(response, self.template)

如果这是处理异常和测试异常的最佳方法,我可能会提出另一个问题,但这将是另一个问题。

谢谢Iulia Chiriac。