在 Validator 对象上模拟 fails() 和 make()

Mocking fails() and make() on a Validator object

我正在尝试使用 Mockery 模拟我从 Validator 对象获得的响应,我正在尝试最终强制通过或失败验证,以便我可以测试会发生什么验证后。我试过以下方法,但并不高兴。

$validator = Validator::shouldReceive('make')
    ->once()
    ->with([], $this->rules);

$validator->shouldReceive('fails')
    ->once()
    ->andReturn(true);

$validator = Validator::shouldReceive('make')
    ->once()
    ->with([], $this->rules)
    ->shouldReceive('fails')
    ->once()
    ->andReturn(true);    

然后我将 class 中的验证器 属性 设置为从 Mockery

返回的对象

我要测试的函数看起来像这样

class JsonModel extends Model
{

    private $validator;

    public function createFromJSON(array $inputData, $throwException = false)
    {
        // This calls Validator::make
        $this->makeValidator(
            $inputData, 
            $this->getValidationRules() // An internal function that returns the rules for the Model
        );

        if($this->validator->fails()) {
             if($throwException === true) {
                 throw new Exception('Validation failed');
             } else {
                 return null;
             }
         }
        return null;

        /** @var Model $model */
        $model = self::create($inputData);
        return $model;
    }

    private function makeValidator($inputData, $ruleData)
    {
        $this->validator = Validator::make($inputData, $ruleData);
    }
}

我对其他方法的建议持开放态度,我修复它不是必需的,因为我可以沿着 return 空路径,删除异常并假设 Validator 会完成它的工作,但这让我很烦.

所以我经过多次修补后找到了答案。这完全与您调用验证器的方式有关。我决定更改函数,以便它所做的只是使用规则集验证对象。所以我现在返回 passes() 而不是 fails() 的结果。对于任何其他试图嘲笑这个的人,下面的内容应该对你有所帮助。

public function testWithMockValidator()
{
    // Mock the function you wish to mock and the result
    $mockValidator = \Mockery::mock('\Illuminate\Validation\Validator');
    $mockValidator->shouldReceive('passes')
        ->once()
        ->andReturn(false);

    // Then Mock the factory that will be used to create the validator
    $factory = '\Illuminate\Validation\Factory';

    $mockFactory = \Mockery::mock($factory);
    $mockFactory->shouldReceive('make')
        ->once()
        ->andReturn($mockValidator);

    // Register the mock with the app
    \App::instance($factory, $mockFactory);

    // Create the object I need
    $obj = \Mockery::mock(self::CLASS_NAME)->makePartial();

    // Set a property using reflection
    $property = UTH::i()->makePropertyAccessible(
        self::CLASS_NAME,
        self::PROP_VALIDATION_RULES
    );
    $property->setValue($obj, $this->rules);

    // call my function (which has been renamed and redesigned to just validate the model
    $return = $obj->validate(['foo' => true]);

    // $return will be whatever you set it to in the mock above
    $this->assertFalse($return);
}

这里是正在测试的class中的函数

public final function validate(array $inputData)
{
    $factory = \App::make('\Illuminate\Validation\Factory');
    // This retrieves the private property
    $rules = $this->getValidationRules();

    $this->validator = $factory->make($inputData, $rules);

    return $this->validator->passes();
}