简体   繁体   English

Laravel嘲弄

[英]Laravel mockery

I am trying to set up the simplest of tests in my controller but, as with most things Laravel, there are no decent tutorials to demonstrate the simple stuff. 我试图在我的控制器中设置最简单的测试,但是,与大多数Laravel一样,没有像样的教程来演示简单的东西。

I can run a simple test (in a file called UserControllerTest) like this: 我可以运行一个简单的测试(在一个名为UserControllerTest的文件中),如下所示:

public function testIndex()
{      
    $this->call('GET', 'users');
    $this->assertViewHas('users');
}

This calls the /users route and passes in an array users. 这将调用/ users路由并传入数组用户。

I want to do the same with Mockery but how? 我想和Mockery一样,但是怎么样?

If I try this: 如果我试试这个:

public function testIndex()
{
  $this->mock->shouldReceive('users')->once();

  $this->call('GET', 'users');

}

I get an error that "Static method Mockery_0_users::all does not exist on this mock object. 我得到一个错误“静态方法Mockery_0_users :: all在这个模拟对象上不存在。

Why not? 为什么不? I am mocking User which extends Ardent and in turn extends Eloquent. 我嘲笑用户扩展了Ardent,反过来扩展了Eloquent。 Why does ::all not exist for the mock? 为什么::所有不存在的模拟?

BTW, these are the set-up functions for Mockery: 顺便说一句,这些是Mockery的设置功能:

public function setUp()
{
  parent::setUp();

  $this->mock = $this->mock('User');
}

public function mock($class)
{
  $mock = Mockery::mock($class);

  $this->app->instance($class, $mock);

  return $mock;
}

You can't directly mock an Eloquent class. 你不能直接嘲笑一个Eloquent类。 Eloquent is not a Facade and your User model neither. Eloquent不是Facade,也不是您的用户模型。 There is a bit of magic in Laravel but you can't do things like that. Laravel有一点魔力,但你不能做那样的事情。

If you want to mock your User class, you have to inject it in the controller constructor. 如果要模拟User类,则必须将其注入控制器构造函数中。 The repository pattern is a good approach if you want to do that. 如果您想这样做,存储库模式是一种很好的方法。 There is a lot of articles about this pattern and Laravel on Google. 在Google上有很多关于这种模式和Laravel的文章。

Here some pieces of code to show you how it could look like : 这里有一些代码片段向您展示它的外观:

class UserController extends BaseController {

    public function __construct(UserRepositoryInterface $users)
    {
        $this->users = $users;
    }

    public function index()
    {
        $users = $this->users->all();
        return View::make('user.index', compact('users'));
    }

}

class UserControllerTest extends TestCase
{

    public function testIndex()
    {
        $repository = m::mock('UserRepositoryInterface');
        $repository->shouldReceive('all')->andReturn(new Collection(array(new User, new User)));
        App::instance('UserRepositoryInterface', $repository);

        $this->call('GET', 'users');
    }

}

If it seems to be too much structuration for your project you can just call a real database in your tests and don't mock your model classes... In a classic project, it just works fine. 如果你的项目看起来结构太多,你可以在你的测试中调用一个真正的数据库,而不是模拟你的模型类......在经典项目中,它只是工作正常。

This function is part of a project called apiato.io you can use it to mock any class in Laravel, even facade, basically anything that can be resolved with the IoC, which is almost all classes if you are using proper dependency injection: 这个函数是一个名为apiato.io的项目的一部分,你可以用它来模拟Laravel中的任何类,甚至是外观,基本上任何可以用IoC解决的东西,如果你使用正确的依赖注入,几乎所有的类都是如此:

/**
 * Mocking helper
 *
 * @param $class
 *
 * @return  \Mockery\MockInterface
 */
public function mock($class)
{
    $mock = Mockery::mock($class);
    App::instance($class, $mock);

    return $mock;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM