使用mockeryBuilder()在没有数据库的情况下测试Yii2中的存在验证器

时间:2017-10-28 14:40:13

标签: activerecord yii2 phpunit codeception mockery

我想测试我的AR模型而不连接到Yii 2中的数据库所以我使用mockBuilder()但我不知道如何将模拟对象传递给模型存在验证器,例如:

class Comment extends ActiveRecord
{
  public function rules()
  {
    return [
      [['id', 'user_id', 'post_id'], 'comment'],
      ['comment', 'string',
        'max' => 200
      ],
      ['user_id', 'exist',
        'targetClass'     => User::className(),
        'targetAttribute' => 'id'
      ],
      ['post_id', 'exist',
        'targetClass'     => Post::className(),
        'targetAttribute' => 'id'
      ]
    ];
  }
}

class CommentTest extends TestCase
{
  public function testValidateCorrectData()
  {
    $user = $this->getMockBuilder(User::className())
      ->setMethods(['find'])
      ->getMock();

    $user->method('find')->willReturn(new User([
      'id' => 1
    ]));

    $post = $this->getMockBuilder(Post::className())
      ->setMethods(['find'])
      ->getMock();

    $post->method('find')->willReturn(new Post([
      'id' => 1
    ]));

    // How can I pass to $user and $post to exist validator in Comment model?

    $comment = new Comment([
      'user_id' => 1,
      'post_id' => 1,
      'comment' => 'test...'
    ]);

    expect_that($comment->validate());
  }
}
好吧,这不是最好的代码,我想介绍一下我想做的事情。

1 个答案:

答案 0 :(得分:0)

Yii2 ExistValidator使用ActiveQuery :: exists()进行检查,你应该将生成的验证器替换为mockobject,其中方法createQuery返回ActiveQuery的mockobject,其中:: exists()返回你想要的东西(true / false),例如

$activeQueryMock = $this->getMockBuilder(ActiveQuery::className())
    ->disableOriginalConstructor()
    ->setMethods(['exists'])
    ->getMock();

$activeQueryMock->expects($this->any())
    ->method('exists')
    ->willReturn($value); //Your value here true/false

$model = $this->getMockBuilder(Comment::className())
    ->setMethods(['getActiveValidators'])
    ->getMock();

$model->expects($this->any())
    ->method('getActiveValidators')
    ->willReturnCallback(function () use ($activeQueryMock) {
        $validators = (new Comment())->activeValidators;
        foreach ($validators as $key => $validator) {
            if (($validator instanceof ExistValidator) && ($validator->attributes = ['user_id'])) {

                $mock = $this->getMockBuilder(ExistValidator::className())
                    ->setConstructorArgs(['config' => get_object_vars($validator)])
                    ->setMethods(['createQuery'])
                    ->getMock();

                $mock->expects($this->any())
                    ->method('createQuery')
                    ->willReturn($activeQueryMock);

                $validators[$key] = $mock;
                break;
            }
        }
        return $validators;
    });

$model->validate();