Laravel:在自定义 Route::model 绑定中使用模拟实例

Posted

技术标签:

【中文标题】Laravel:在自定义 Route::model 绑定中使用模拟实例【英文标题】:Laravel: Using mock instance in Customised Route::model binding 【发布时间】:2018-03-03 10:11:49 【问题描述】:

Laravel 中的路由模型绑定,有助于将实例绑定到服务容器,以用于控制器操作。美妙的是,当我想编写测试时,我可以将一个模拟实例绑定到应用程序,它取代了绑定到容器的内容。 - App::instance($className, $mockInstance);

我已向路由 (Route::get("/class_name")) 提出请求。我想返回一个类的实例,这取决于路由参数class_name 的值是什么。

如果值为two,我想要Two 类的实例,One 类的实例也是如此。请注意,这两个类都继承自 AbstractClass,因此返回的实例类型为 AbstractClass,(php7)。

问题:当我访问路线时,我得到了正确的实例。但是当我想使用模拟实例时,它会覆盖模拟实例并创建/返回主实例。我需要使用模拟实例,以便对它设置期望。

我添加了一些代码,希望能说明我的意思。

abstract class AbstractClass 
// abstract parent class


class One extends AbstractClass 
// single child class


class Two extends AbstractClass 
// another single child class


// I put this inside the `bind` method of the RouteServiceProvider
Route::bind("class_name", function (string $class_name) : AbstractClass 
 // I wish to return an instance to the route, based on the string that was passed - "one" or "two"
 $class = ucfirst($class_name);
 return new $class();
);

// test
public function testSomething () 
 $mockInstance = Mockery::mock(AbstractClass::class);
 App::instance(AbstractClass::class, $mockInstance);
 $response = $this->get("/one");

// controller method
public function action (AbstractClass $instance) 
 // I want to see/use the mock instance here, for testing
 // and the main instance otherwise.

我用的是PHP7.0,用Laravel5.4开发

【问题讨论】:

我尝试过使用$this->app->runningUnitTests(),首先在绑定之前检查我是否正在运行测试,这允许我使用模拟实例,但这也会影响我不想使用的测试模拟实例,但主要实例。在某些测试用例中,由于对某些外部 API 的某些调用,我需要模拟实例。 【参考方案1】:

原因: 好吧,我猜你混淆了Router bindingsContainer Bindings。这两者本质上是完全不同的。

答案: 只需在编写测试时更新路由器绑定即可。

        $mock = Mockery::mock(AbstractClass::class);

        $this->app->get('router')->bind('class', function () use ($mock) 
             return $mock;
        );

        $response = $this->get("/test");

路由器绑定: 这些绑定只有在涉及路由时才会被解析,而当你使用app() 实例时无法解析。

容器绑定: 容器绑定是独立的,它根本不知道路由器绑定。

【讨论】:

以上是关于Laravel:在自定义 Route::model 绑定中使用模拟实例的主要内容,如果未能解决你的问题,请参考以下文章

Laravel:在自定义登录中集成 Throttle

Laravel - 在自定义验证中使用验证规则

在自定义主键和外键中定义 Laravel 关系

在自定义验证中使用 Angular JS + Laravel 检查当前密码

Laravel Route 模型与关系绑定

如何在自定义 URL 上运行 Laravel mix?