我想阻止模拟事件,例如' created'。 '更新'等,使用phpunit测试我的应用程序。
在Laravel的文档中,它说您可以使用
防止事件被触发 $this->expectsEvents(App\Events\UserRegistered::class);
但在我的情况下,我没有期望的课程。
即使我使用$this->withoutEvents();
来阻止所有事件,也会触发雄辩的事件。
如何防止有说服力的事件?
答案 0 :(得分:9)
调查Laravel Api Model::flushEventListeners()
应该"删除该模型的所有事件监听器。"
修改
您可以在此基础上编写自定义方法:
public static function flushEventListeners()
{
if (! isset(static::$dispatcher)) {
return;
}
$instance = new static;
foreach ($instance->getObservableEvents() as $event) {
static::$dispatcher->forget("eloquent.{$event}: ".get_called_class());
}
}
这样的事情可能是:
public static function flushEventListenersProvided($events)
{
if (! isset(static::$dispatcher)) {
return;
}
$instance = new static;
foreach ($instance->getObservableEvents() as $event) {
if(in_array($event, $events)){
static::$dispatcher->forget("eloquent.{$event}: ".get_called_class());
}
}
}
并且可能将其添加为模型的特征,或者所有模型将扩展的基本模型。此代码未经测试,但应该让您了解如何完成。
答案 1 :(得分:1)
查看shouldReceive
课程的Model
方法。基本上Model
类扩展Mockery
。
这是一个假设你有一个班级Car
的例子:
Car::shouldReceive('save')->once();
这不会命中数据库,而是会使用mock。您可以在此处找到有关Laravel测试的更多信息:http://laravel.com/docs/4.2/testing
希望这有帮助。
答案 2 :(得分:1)
你应该可以使用
$model = new App\Model($inputs);
$this->expectsEvents(['eloquent.creating: App\Model', 'eloquent.saved: App\Model']);
$model->save();
答案 3 :(得分:1)
如果您真的只想禁用模型的观察者,例如creating
,created
,updated
等,则可以调用模型的外观方法unsetEventDispatcher
。
例如,您可以将其放在测试类的setUp
方法中。而且您不必在tearDown
中将其重置,因为框架会在setUp
中为下一次测试自动执行此操作。
protected function setUp(): void
{
parent::setUp();
App\MyModel::unsetEventDispatcher();
}
如果您希望这是临时的,请查看withoutEventDispatcher
。
此外,您可以getEventDispatcher
并将其保存到临时变量中,然后在完成业务后再次setEventDispatcher
,如以下答案所示:https://stackoverflow.com/a/51301753/4233593
答案 4 :(得分:0)
方法1:
您可以通过模拟Observer来阻止模型事件触发。以下是:
public function my_sexy_test()
{
$this->app->bind(MyModelObserver::class, function () {
return $this->getMockBuilder(MyModelObserver::class)->disableOriginalConstructor()->getMock();
});
factory(MyModel::class)->states('pending')->create([
'user_id' => 1,
'publisher_revenue' => 10,
]);
// Your test logic goes here
}
方法2:
您可以在setUp()方法中调用以下内容:
MyModel::unsetEventDispatcher();
在Laravel 5.6中进行了测试和工作。