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

Posted

技术标签:

【中文标题】使用 mockeryBuilder() 在没有数据库的情况下测试 Yii2 中的存在验证器【英文标题】:Test the exist validator in Yii2 without database with mockeryBuilder() 【发布时间】:2018-04-09 23:53:28 【问题描述】:

我想在 Yii 2 中测试我的 AR 模型而不连接到数据库,所以我使用 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】:

Yii2 ExistValidator 使用 ActiveQuery::exists() 来检查是否存在,您应该将生成的验证器替换为模拟对象,其中 createQuery 方法返回 ActiveQuery 的模拟对象,其中 ::exists() 返回您想要的东西(真/假),例如

$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();

【讨论】:

以上是关于使用 mockeryBuilder() 在没有数据库的情况下测试 Yii2 中的存在验证器的主要内容,如果未能解决你的问题,请参考以下文章

使用 NSFetchedResultsController 在 tableView 中没有数据视图

如果 body:Form 没有在颤振应用程序中使用,我的表单数据没有被提交或保存

UITableView 没有在 Swift 3 中使用 Index 正确显示数据

有没有办法在没有数据库的情况下使用 laravel 4.2 身份验证?

在没有实时数据的情况下使用 ViewModel 可以吗

在没有 Laravel 的情况下使用 Laravel 数据库迁移和种子 [关闭]