【问题标题】:Laravel 5.2 Unit Testing Repository with Mocking "does not have method"Laravel 5.2 带有 Mocking 的单元测试存储库“没有方法”
【发布时间】:2016-04-13 09:28:21
【问题描述】:

在 Laravel 5.2 中,我想对我的 Eloquent 用户存储库进行单元测试。

class EloquentUserRepository implements UserRepositoryInterface
{
    private $user;

    public function __construct(User $user)
    {
        $this->user = $user;
    }

    public function oneUser($id)
    {
        return $this->user->oneUser($id);
    }
}

我的测试如下所示,模拟界面:

class EloquentUserRepositoryTest extends TestCase
{
    public function setUp()
    {
        $this->user = factory(User::class, 1)->create(['name' => 'foo']);
    }

    /** @test */
    public function it_fetch_an_user()
    {

        $mock = Mockery::mock('App\Repositories\Interfaces\UserRepositoryInterface')
        ->shouldReceive('oneUser')
        ->once()
        ->with($this->user->id)
        ->andReturn('foo');

        App::instance(App\Repositories\EloquentUserRepository::class, $mock);
        $userRepository = App::make(App\Repositories\EloquentUserRepository::class);

        $this->assertEquals('foo', $userRepository->oneUser($this->user->id)->name);

    }

    public function tearDown()
    {
        Mockery::close();
    }
}

我收到此错误:

ErrorException: call_user_func_array() expects parameter 1 to be a valid callback, class 'Mockery\Expectation' does not have a method 'oneUser'

我期望一个具有 oneUser 方法的模拟对象,但它返回 Mockery\Expectation。我哪里错了?

【问题讨论】:

    标签: unit-testing laravel-5 phpunit mockery


    【解决方案1】:

    当创建 EloquentUserRepository 的新实例时,会创建一个新的用户模型。然后,当您为 EloquentUserRepository 类调用 oneUser 方法时,会调用一个具有相同名称但在用户模型上的方法。因此,您需要模拟的是用户模型,而不是 UserRepositoryInterface。

    您需要创建 EloquentUserRepository 的新实例,并在创建时将用户模型模拟作为参数发送,如下所示:

    class EloquentUserRepositoryTest extends TestCase
    {
        protected $userMock;
    
        public function setUp()
        {
            parent::setUp();
    
            $this->userMock = Mockery::mock('User');
            $this->userMock->id = 1;
        }
    
        /** @test */
        public function it_fetch_an_user()
        {
            $this->userMock->shouldReceive('oneUser')->with($this->userMock->id)->andReturn('foo');
    
            $userRepository = App::make(App\Repositories\EloquentUserRepository::class, array($this->userMock));
    
            $this->assertEquals('foo', $userRepository->oneUser($this->userMock->id));
        }
    
        public function tearDown()
        {
            Mockery::close();
        }
    }
    

    【讨论】:

    • 只是一个评论,我怀疑这是正确的答案。当您模拟模型User 时,这意味着例如有一天您要切换出 Eloquent;您将需要重构您的测试并使用MongoUser 之类的东西删除模型User。这与存储库模式相矛盾。我的理解是,在切换接口的实现时,您不应该重构您的测试。
    • 作为我之前评论的补充。我搜索了网络,聪明的人倾向于建议我们不应该测试存储库。我们宁愿编写集成测试来测试我们的存储库调用是否有效。我认为他们说得有道理。请查看 url url https://laracasts.com/discuss/channels/testing/phpunit-testing-repositories 祝你好运。还请记住:Brilliance is evenly distributed.
    猜你喜欢
    • 1970-01-01
    • 2019-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多