【问题标题】:Mock object giving bad method call exception PHPUnit模拟对象给出错误的方法调用异常 PHPUnit
【发布时间】:2018-07-22 20:07:46
【问题描述】:

测试下面的方法

public function handle($loginDetails): User
{
    $authUser = $this->user->where('user_id', $loginDetails->id)->first();
    if (!$authUser) {
        $authUser = $this->user->create([
            'name' => $loginDetails->name,
            'email' => $loginDetails->email,
            'profile_image' => $loginDetails->avatar_original,
            'user_id' => $loginDetails->id
        ]);
    }

    return $authUser;
}

我正在模拟和测试它如下

public function shouldHandleNewUser()
{
        $mockBuilder = $this->getMockBuilder(Builder::class)
            ->disableOriginalConstructor()
            ->setMethods(['first'])
            ->getMock();
        $mockBuilder->method('first')
            ->willReturn(null);

        $mockUser = $this->getMockBuilder(User::class)
            ->disableOriginalConstructor()
            ->setMethods(['where', 'create'])
            ->getMock();

        $mockUser->method('where')
            ->willReturn($mockBuilder);

        $mockUser->method('create')
            ->willReturn(new User());

        $loginDetails = new class {
            public $id = 1;
            public $name = 'testUser';
            public $email = 'test@test.com';
            public $avatar_original = 'http://someurl.com/image.jpg';
        };

        $registrationHandler = new RegistrationHandler($mockUser);
        $this->assertInstanceOf(User::class, $registrationHandler->handle($loginDetails));
}

当它到达create 方法时,它正在抛出

PHPUnit_Framework_MockObject_BadMethodCallException

我在这里做错了什么?

【问题讨论】:

    标签: php unit-testing laravel-5


    【解决方案1】:

    你不能用 PHPUnit 模拟 static 方法(我假设 User::create() 是静态的)。

    限制:final、private 和 static 方法

    请注意finalprivateprotectedstatic 方法不能 被嘲笑或嘲笑。它们被 PHPUnit 的测试替身忽略 功能并保留其原始行为。

    曾经有一个staticExpects() 方法来解决它。它在 PHPUnit 3.8 中被弃用并在 PHPUnit 3.9 中被删除。作为Sebastian Bergmann says,解决办法是不使用static方法(我同意他的观点)

    【讨论】:

    • 你是对的,它恰好是 Laravel Eloquent 中的静态方法。有什么解决办法吗?
    • Eloquent 模型的问题在于它们实际上是 Active Record 模式的实现,这意味着它们将持久性和业务逻辑紧密结合在一起,并且它们充满了静态方法,这使得类很难测试。如果你能够使用Mockery(我认为它是 Laravel 自带的),请查看this 问题。
    • 感谢您的解释。我将代码从使用 static create 方法更改为 Eloquent save 中的实例方法。通过更改代码以满足测试,我有点难过。但是你的解释清除了我的概念。谢谢
    • Raheel,我认为重构是编码的重要组成部分,所以不要难过!也就是说,有很多关于单元测试 Eloquent 模型的信息(我见过人们只是对它们进行集成测试而不是单元测试),所以一定要找一些文章,也许你可以保留你的代码!以下是一些:firstsecond。祝你好运!
    猜你喜欢
    • 2022-08-22
    • 2018-02-04
    • 1970-01-01
    • 2011-02-19
    • 2013-09-12
    • 2010-09-25
    • 2014-11-07
    • 2016-04-21
    • 2011-10-28
    相关资源
    最近更新 更多