PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Tuesday, March 1, 2022

[FIXED] Mocking Laravel custom validation rule class not working

 March 01, 2022     laravel-5, phpunit     No comments   

Issue

I'm implementing a new custom validation rule in form submit. But I want to bypass the validation rule in unit testing. Below is the simplified of the validation rule and unit test class. What am I missing?

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class Captcha implements Rule
{
    public function passes($attribute, $value)
    {
        // assuming will always return false in testing
        // works fine when true
        return false; 
    }

    public function message()
    {
        return 'Captcha error! Try again later or contact site admin.';
    }
}
use Tests\TestCase;
use App\Rules\Captcha;

class RegistrationTest extends TestCase {

    public test_user_registration()
    {
        $this->mock(Captcha::class, function ($mock) {
            $mock->shouldReceive('passes')->andReturn(true);
        });

        $response = $this->post(route('tenant.register'), [
            'g-recaptcha-response' => 1,
            'email' => 'user@example.com',
            'password' => 'secret',
        ]);

        $this->assertEquals(1, User::all()->count());
     }
} 

EDIT: included FormRequest and Controller file as well

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use App\Rules\Captcha;

class NewUserRequest extends FormRequest {

    public function rules()
    {
        return [
            'name' => ['required', new Captcha]
        ];
    }
}
...

public function postRegister(NewUserRequest $request) {

...

EDIT II: seems like a bug in Laravel itself;

  • https://github.com/laravel/framework/issues/28468
  • https://github.com/laravel/framework/issues/19450
  • https://github.com/laravel/framework/issues/25041

tried the provided solutions but still not working


Solution

The class must be instantiated through Laravels service container in order for it to be mocked. The best way to accomplish this (in this situation) is to simply change new Captcha to app(Captcha::class):

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use App\Rules\Captcha;

class NewUserRequest extends FormRequest {

    public function rules()
    {
        return [
            'name' => ['required', app(Captcha::class)]
        ];
    }
}

I would advise against telling the rule itself to change its behaviors based on environments as that could result in a bit of confusion down the line when you are trying to figure out why the captcha doesn't do anything in dev environments but is failing in production.



Answered By - Brett
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing