php - 如何在 php 测试中使用模拟对象

标签 php laravel testing phpunit

我正在尝试学习如何正确测试,并且正在努力了解下面场景中的模拟。我似乎无法 mock 一个类。

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

这是在 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]);

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

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

最佳答案

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

$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');

关于php - 如何在 php 测试中使用模拟对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49480999/

相关文章:

php - Laravel:使用 `configureMonologUsing()` 的多个日志提供程序?

javascript - Adsense 广告未出现

php - 验证在 php 中生成的 nodejs 中的密码哈希

php - 如何在从 php laravel 中的 Controller 上传之前显示图像预览

java - 如何选取部分测试用例组成BAT测试(构建验收测试)?

testing - Amazon EC2 原型(prototype)制作

c++ - 如何在 Visual Studio 中测试已编译的 DLL(或生成多个可执行文件)?

php - 使用 php-cs-fixer 修复 PHP 代码文件的缩进

PHP/MySQL : querying MySQL with an array and getting results in an array

Laravel 5.5 未找到具有正确命名空间的类