【问题标题】:How to use mock objects in php testing如何在 php 测试中使用 mock 对象
【发布时间】:2023-04-09 00:12:01
【问题描述】:

我正在努力学习如何正确测试,并且在下面的场景中努力理解模拟。我似乎无法模拟一堂课。

主类使用许多组件类来构建特定的活动。我可以自己测试组件并正确模拟它,但是当我尝试在主类中集成测试时,它调用的是真实服务而不是模拟服务。

这是在 Laravel 5.5 应用程序中。

我有一个基类:

class booking {

private $calEventCreator

    public function __construct(CalenderEventCreator $calEventCreator) {
       $this->calEventCreator = $calEventCreator;
    }
}

然后由另一个类扩展:

class EventType extends booking {

    //do stuff
}

CalenderEventCreator 依赖于我要模拟的外部服务。

class CalendarEventCreator {

    public function  __construct(ExternalService $externalService) {

        $this->externalService = $externalService;

    }
}

在我的测试中,我尝试了以下操作:

public function test_complete_golf_booking_is_created_no_ticket()
{

    $this->booking = \App::make(\App\Booking\EventType::class);

    $calendarMock = \Mockery::mock(ExternalService::class);

    $calendarMock->shouldReceive([
        'create' => 'return value 1',
    ])->once();

    $this->booking->handle($this->attributes, 'booking');

}

但在尝试执行测试时,很明显 ExyernalService 没有使用模拟对象。

我尝试重新排列代码如下:

$calendarMock = \Mockery::mock(Event::class);
    $calendarMock->shouldReceive([
        'create' => 'return value 1',
    ])->once();

    $this->booking = \App::make(\App\Booking\EventType::class);

    $this->booking->handle($this->attributes, 'booking');
}

并尝试过:

$this->booking = \App::make(\App\Booking\EventType::class, ['eventService'=>$calendarMock]);

但每次调用真正的服务而不是模拟版本

我正在学习这一点,因此对基本错误表示歉意,但有人可以解释我应该如何正确模拟外部服务

【问题讨论】:

    标签: php laravel testing phpunit


    【解决方案1】:

    也许有更好的方法来实现这一点,但我正在使用以下方法:

    $calendarMock = \Mockery::mock(ExternalService::class);
    $calendarMock->shouldReceive([
        'create' => 'return value 1',
    ])->once();
    
    $this->booking = new \App\Booking\EventType($calendarMock);
    $this->booking->handle($this->attributes, 'booking');
    

    我没有使用服务容器来解析类,而是直接通过模拟服务调用构造函数。

    更新

    寻找其他方法来做到这一点,我找到了this answer。使用该解决方案,您的代码将如下所示:

    $calendarMock = \Mockery::mock(ExternalService::class);
    $calendarMock->shouldReceive([
        'create' => 'return value 1',
    ])->once();
    $this->app->instance(ExternalService::class, $mock);
    
    $this->booking = \App::make(\App\Booking\EventType::class);
    $this->booking->handle($this->attributes, 'booking');
    

    【讨论】:

    • 谢谢 - 这已经成功了,并且模拟正在按预期使用。杰出的!!! :)
    猜你喜欢
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    • 1970-01-01
    • 2016-07-15
    • 2012-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多