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

haakym's avatar

Writing test with form that uses no-captcha

I am writing a test for when a user registers. The registration form has a no-captcha field to prevent bots. I am using the following package to enable the no-captcha functionality: https://github.com/anhskohbo/no-captcha

There are some instructions on the readme with how to use the package when writing tests in Laravel, see here: https://github.com/anhskohbo/no-captcha#testing. However, I'm still running into issues so if anyone could help with writing the tests I would be grateful.

Here's my code...

RegistrationTest.php

/** @test */
public function a_user_can_register()
{
    // prevent validation error on captcha
    NoCaptcha::shouldReceive('verifyResponse')
        ->once()
        ->andReturn(true);

    // provide hidden input for your 'required' validation
    NoCaptcha::shouldReceive('display')
        ->zeroOrMoreTimes()
        ->andReturn('<input type="hidden" name="g-recaptcha-response" value="1" />');
    
    $response = $this->json('POST', '/register', [
        'name' => 'John Doe',
        'email' => '[email protected]',
        'contact_number' => '12345678',
        'account_type' => 'personal',
        'password' => '123456',
        'password_confirmation' => '123456',
    ]);

    $response->assertRedirect('/auth/verification/sent');

    $this->assertDatabaseHas('users', [
        'name' => 'John Doe',
        'email' => '[email protected]',
        'contact_number' => '12345678',
        'account_type' => 'personal',
        'password' => bcrypt('123456'),
        'verified' => 0,
    ]);
}

RegisterController.php (irrelevant methods stripped out)

protected $redirectAfterTokenGeneration = '/auth/verification/sent';

protected function validator(array $data)
{
    return Validator::make($data, [
        'name' => 'required|string|max:255',
        'email' => 'required|string|email|max:255|unique:users',
        'contact_number' => 'required|string|between:8,255',
        'account_type' => 'required|string|in:personal,agent',
        'password' => 'required|string|confirmed|min:6',
        'g-recaptcha-response' => 'required|captcha',
    ], [
        'g-recaptcha-response.required' => 'Please confirm you are not a robot.',
        'g-recaptcha-response.captcha' => 'You have failed to confirm you are not a robot, please try again.',
    ]);
}

public function register(Request $request)
{
    $this->validator($request->all())->validate();

    DB::beginTransaction();

    try {

        Auth::login($this->create($request->all()));

        $user = auth()->user();

        UserVerification::generate($user);

        UserVerification::send($user, 'UKSACB | Attestation - Account Verification');

    } catch(\Exception $e) {
        DB::rollback();
        throw $e;
    }

    DB::commit();

    return redirect($this->redirectAfterTokenGeneration);
}

protected function create(array $data)
{
    $user = User::create([
        'name' => $data['name'],
        'email' => $data['email'],
        'contact_number' => $data['contact_number'],
        'password' => bcrypt($data['password']),
    ]);

    $user = $this->assignRoles($user, $data['account_type']);

    return $user;
}

When running the test vendor\bin\phpunit --filter=a_user_can_register I get the following:

There was 1 failure:

1) RegistrationTest::a_user_can_register
Response status code [422] is not a redirect status code.
Failed asserting that false is true.

C:\laragon\www\attestation\vendor\laravel\framework\src\Illuminate\Foundation\Testing\TestResponse.php:92
C:\laragon\www\attestation\tests\Feature\Auth\RegistrationTest.php:36

When adding dd($response->getContent()); directly after the POST request, I see the following in my terminal:

"{"message":"The given data was invalid.","errors":{"g-recaptcha-response":["Please confirm you are not a robot."]}}"

Any ideas? Thanks.

0 likes
2 replies
haakym's avatar
haakym
OP
Best Answer
Level 8

I got it working after modifying the POST data to include the g-recaptcha-response with a value of 1, as the g-recaptcha-response.required rule was failing so it needed to be added to the data being sent over. This would essentially be fulfilling the same purpose as the following code block:

// provide hidden input for your 'required' validation
NoCaptcha::shouldReceive('display')
    ->zeroOrMoreTimes()
    ->andReturn('<input type="hidden" name="g-recaptcha-response" value="1" />');

which I removed.

The POST request now looks like this:

$response = $this->json('POST', '/register', [
    'name' => 'John Doe',
    'email' => '[email protected]',
    'contact_number' => '12345678',
    'account_type' => 'personal',
    'password' => '123456',
    'password_confirmation' => '123456',
    'g-recaptcha-response' => '1',
]);
1 like

Please or to participate in this conversation.