【问题标题】:Django - Unit testing a form containing recaptchaDjango - 对包含 recaptcha 的表单进行单元测试
【发布时间】:2023-11-15 14:39:01
【问题描述】:

我正在尝试为包含 recaptcha 的表单编写单元测试:

我的联系人视图如下所示:

@check_recaptcha
def contact(request):
    if request.method == 'POST':
        f = ContactForm(request.POST)
        if f.is_valid() and request.recaptcha_is_valid:

            f.save(request)
            messages.add_message(request, messages.INFO, "Thanks for submitting feedback!")


            return redirect('contact')
    else:
        f = ContactForm()

    return render(request, 'cms/contact.html', {'form': f})

装饰器check_recaptcha()是这样定义的:

def check_recaptcha(view_func):
    @wraps(view_func)
    def _wrapped_view(request, *args, **kwargs):
        request.recaptcha_is_valid = None

        if settings.DEBUG:
            request.recaptcha_is_valid = True
            return view_func(request, *args, **kwargs)

        if request.method == 'POST':
            recaptcha_response = request.POST.get('g-recaptcha-response')
            data = {
                'secret': settings.GOOGLE_RECAPTCHA_SECRET_KEY,
                'response': recaptcha_response
            }
            r = requests.post('https://www.google.com/recaptcha/api/siteverify', data=data)
            result = r.json()
            if result['success']:
                request.recaptcha_is_valid = True
            else:
                request.recaptcha_is_valid = False
                messages.error(request, 'Invalid reCAPTCHA. Please try again.')

        return view_func(request, *args, **kwargs)
    return _wrapped_view

测试联系表单的代码如下所示:

class TestContactForm(TestCase):

    def test_can_send_feedback(self):
        data = {
            "name": "tom",
            "email": "tom@test.com",
            "subject": "A test subject",
            "message": "Hello jerry",
        }

        response = self.client.post(reverse('contact'), data=data)
        self.assertEqual(Feedback.objects.count(), 1)
        self.assertEquals(response.status_code, 302)
        self.assertRedirects(response, reverse('contact'))

如果我删除 contact 视图中的 request.recaptcha_is_valid 条件,测试运行得非常好。有没有办法在测试期间摆脱验证码?

【问题讨论】:

    标签: python django unit-testing recaptcha captcha


    【解决方案1】:

    有一个用于测试验证码表单的特定键:https://developers.google.com/recaptcha/docs/faq#id-like-to-run-automated-tests-with-recaptcha.-what-should-i-do

    否则,您也可以使用 https://requests-mock.readthedocs.io/en/latest/ 模拟您的 resquests 响应

    【讨论】:

      【解决方案2】:

      附加到 hendrikschneider 答案 (https://developers.google.com/recaptcha/docs/faq#id-like-to-run-automated-tests-with-recaptcha.-what-should-i-do)。如果你想测试单元测试,设置GOOGLE_RECAPTCHA_SECRET_KEY V3 使用测试密钥(为测试环境创建一个单独的密钥),V2 密钥使用6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe 就像提到的常见问题。如果使用 V3,请记住将您的域设置为 localhost

      对于g-recaptcha-response,将其设置为任何可以做的事情

      【讨论】: