如何在 Laravel 中模拟验证规则

问题描述 投票:0回答:2

我想模拟自定义验证规则(例如 App\Rules\SomeRule)。但是当我运行测试时,它给出了

Mockery\Exception\InvalidCountException: Method...should be called
 exactly 1 times but called 0 times.

我已经阅读了 Laravel 的文档关于模拟关于自定义验证规则服务容器服务提供商,我不明白为什么我没有成功地模拟规则。

我读了这个线程,但我很难将它与我的问题联系起来,即“如何测试我的应用程序是否正在使用此规则”。或者这是我无法测试的东西?

这是我的规则

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class SomeRule implements Rule
{

    public function passes($attribute, $value)
    {
        // some logic, returns TRUE if valid.
    }

    public function message()
    {
        //
    }
}

我的控制器

namespace App\Http\Controllers;

use App\Rules\SomeRule;
use Illuminate\Http\Request;

class LoanController extends Controller
{
    public function store(Request $request)
    {
        $request->validate([
            'email' => ['required', new SomeRule]
        ]);

        // ...insert in database, return json.
    }
}

我的测试

namespace Tests\Feature;

use Mockery;
use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;
use App\Rules\SomeRule;

class LoansTest extends TestCase
{
    use RefreshDatabase;

    public function tearDown(): void
    {
        parent::tearDown();
        Mockery::close();
    }

    /** @test */
    public function the_sad_path__when_email_is_invalid()
    {

        $rule = Mockery::mock(SomeRule::class)->shouldReceive('passes')->once();
        $this->app->instance(SomeRule::class, $rule);

        $response = $this->json('POST', '/api/loans', ['email' => '[email protected]']);
    }
}

我考虑了在 AppServiceProvider 中注册 SomeRule 的想法。但这仍然没有起到任何作用:

    public function register()
    {
        $this->app->bind(SomeRule::class, function ($app) {
            return new SomeRule();
        });
    }

代码在Github

php laravel mocking mockery
2个回答
0
投票

解决此问题的一种方法是更新控制器以将

SomeRule
的分辨率推迟到容器:

public function store(Request $request, Application $app)
{
    $request->validate([
        'email' => ['required', $app->make(SomeRule::class)]
    ]);
}

这样,当我们在测试中将模拟对象绑定到

SomeRule::class
时,容器就有机会解析模拟对象而不是具体实例。

您可以通过直接在控制器方法上键入提示

SomeRule
来进一步简化这一步骤:

public function store(Request $request, SomeRule $someRule)
{
    $request->validate([
        'email' => ['required', $someRule]
    ]);
}

对于那些使用较新版本的 Laravel 的人来说,使用一些语法糖创建模拟并将其绑定到容器现在变得更加简单:

/** @test */
public function the_sad_path__when_email_is_invalid()
{
    $this->mock(SomeRule::class)->expects('passes');
    
    // ...
}

-1
投票

你需要这样使用

class LoanController extends Controller
{
    public function store(Request $request)
    {
      $request->validate([
        'email' => ['required', new SomeRule()]
      ]);

    // ...insert in database, return json.
   }
}
© www.soinside.com 2019 - 2024. All rights reserved.