使用find()模拟Eloquent模型

ney*_*eyl 9 phpunit laravel laravel-4

我试图用Mockery模拟Eloquent模型.模型正在Controller中注入

__construct(Post $model){$this->model=$model}
Run Code Online (Sandbox Code Playgroud)

现在我find()在控制器中调用该函数

$post = $this->model->find($id);
Run Code Online (Sandbox Code Playgroud)

这里是PostsController的测试

class PostsTest extends TestCase{

      protected $mock;

      public function setUp() {
        parent::setUp();
        $this->mock = Mockery::mock('Eloquent', 'Posts'); /*According to Jeffrey Way you have to add Eloquent in this function call to be able to use certain methods from model*/
        $this->app->instance('Posts', $this->mock);
      }

      public function tearDown() {

        Mockery::close();
      }

      public function testGetEdit()
      {
        $this->mock->shouldReceive('find')->with(1)->once()->andReturn(array('id'=>1));

        $this->call('GET', 'admin/posts/edit/1');

        $this->assertViewHas('post', array('id'=>1));
      }
    }
Run Code Online (Sandbox Code Playgroud)

运行PhpUnit给我错误:

Fatal error: Using $this when not in object context in ...\www\l4\vendor\mockery\mockery\library\Mockery\Generator.php(130) : eval()'d code on line 73
Run Code Online (Sandbox Code Playgroud)

这显然是因为find()声明为静态函数.现在,代码可以正常运行,因此如何在不失败的情况下成功模拟Eloquent模型.由于我们依赖于依赖注入,我必须find()非静态地调用,否则我可以这样做Post::find().

我想出的一个解决方案是创建一个非静态find()替换BaseModel

public function nsFind($id, $columns = array('*'))
{
  return self::find($id, $columns);
}
Run Code Online (Sandbox Code Playgroud)

但这是一个很大的痛苦,因为功能必须有不同的名字!

我做错了什么或者你有更好的想法吗?

Jef*_*Way 6

嘲弄雄辩的模型是一件非常棘手的事情.本书对此进行了介绍,但我特别注意到这是一个止损.最好使用存储库.

但是,要回答您的问题,问题是您没有在构造函数中执行模拟.这是让它发挥作用的唯一途径.这不理想,我不推荐它.


Fel*_*lix 2

我认为这就是原因,Jeffrey 在他的书《Laravel 测试解码》(第 10 章)中介绍了存储库。

Mockery 在其自述文件中也有关于静态方法的部分,请参阅https://github.com/padraic/mockery#mocking-public-static-methods

  • 我正在读这本书(很棒的书)。然而,Jeffrey 没有提及任何有关此问题的内容,并且在 Jeffrey 的 Generator Helper Package 中,他引入了新的generate:scaffold artisan 命令,该命令生成 PHPUnit 测试,并且他正在使用这种样式(无存储库)并调用 find() 函数。现在,这些测试也失败了!我看过其他使用 find 方法的资源,但没有人提到任何内容! (2认同)