Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

rbruhn's avatar
Level 2

Register Form with ReCaptcha v3

I'm diving into testing and trying to test a registration form that includes Google reCaptcha V3. I've done a lot of searching here and on the net trying to find this solution. I've tried several that I've come across but none work. Below is the templates and code involved. Would appreciate any help.

recaptcha.blade.php

<script type="text/javascript">
        $(function () {
            $('.recaptcha').on('submit', function (event) {
                event.preventDefault();
                grecaptcha.ready(function () {
                    grecaptcha.execute("{{ config('services.recaptcha.site_key') }}", {action: 'submit'}).then(function (token) {
                        $('.recaptcha').append('<input type="hidden" name="g-recaptcha-response" value="' + token + '">');
                        $('.recaptcha').unbind('submit').submit();
                    });
                });
            });
        });
    </script>

RegisterFormRequest.php

public function rules(): array
public function rules(): array
{
    return [
        'first_name'            => 'required',
        'last_name'             => 'required',
        'email'                     => 'required|min:4|max:32|email|unique:users',
        'password'              => 'required|min:6|confirmed',
        'password_confirmation' => 'required',
        'timezone'              => 'required',
        'g-recaptcha-response' => app(ReCaptcha::class),
    ];
}	

ReCaptcha.php

public function validate(string $attribute, mixed $value, Closure $fail): void
{
    $response = Http::asForm()->post(config('services.recaptcha.url'), [
        'secret'   => config('services.recaptcha.secret_key'),
        'response' => $value,
    ]);

    if (! ($response->json()["success"] ?? false)) {
        $fail('The google recaptcha response failed.');
    }
}

I'm using Pest and have this much for the test already. However, it fails due to the recaptcha.

it('can register', function () {
    $response = $this->post('/register', [
        'first_name'            => 'Joe Dirt',
        'last_name'             => 'Jones',
        'email'                 => '[email protected]',
        'password'              => 'somethingrandom ',
        'password_confirmation' => 'somethingrandom ',
        'timezone'              => 'America/New_York',
        'g-recaptcha-response'  => '????????',
    ])->assertRedirect('email/verify');

    $this->assertDatabaseHas('users', [
        'email'      => '[email protected]',
    ]);

    $this->assertDatabaseHas('profiles', [
        'first_name'            => 'Joe',
        'last_name'             => 'Dirt',
        'timezone'              => 'America/New_York',
    ]);
});
0 likes
4 replies
aleahy's avatar
aleahy
Best Answer
Level 25

@rbruhn Since your Recaptcha validation uses the Http facade to do the validation, you can set up your test to mock the response:

Http::fake([
   config('services.recaptcha.url') => Http::response(['success' => true])
]);

This way you don't hit google at all in the test and you can control the recaptcha response.

https://laravel.com/docs/11.x/http-client#testing

martinbean's avatar

@rbruhn I don’t use Pest but you’re resolving the ReCaptcha rule from the service container; in a PHPUnit-based you’d be able to mock that like this:

public function testValidCaptchaTokenIsRequired(): void
{
    $this->mock(ReCaptcha::class, function (MockInterface $mock): void {
        $mock->shouldReceive()->once()->withArgs(function ($attribute, $value): bool {
            $this->assertSame('g-recaptcha-response', $attribute);
            $this->assertSame('VALID_RESPONSE', $token);
            return true;
        })->andReturnTrue();
    });

    $this
        ->post('/register', [
            // Other fields...
            'g-recaptcha-response' => 'VALID_RESPONSE',
        ])
        ->assertRedirect('/email/verify');

    // Other assertions...
}

I imagine you must be able to do the same in Pest.

This way, you’re mocking the actual service being resolved, and not its implementation details.

rbruhn's avatar
Level 2

@martinbean I tried your solution but it threw an error:

Mockery\Exception\BadMethodCallException: Method Mockery_0__ReCaptcha::andReturnTrue() does not exist on this mock object
at tests/Feature/RegisterPageTest.php:50

Played around with it by altering some things and still couldn't get it to work. After trying @aleahy's answer it worked perfectly. Thanks for the help.

Please or to participate in this conversation.