Php 使用Laravel/流明立面进行测试
因此,我试图为一段使用facade的代码编写一个单元测试,它如下所示:Php 使用Laravel/流明立面进行测试,php,unit-testing,laravel,lumen,Php,Unit Testing,Laravel,Lumen,因此,我试图为一段使用facade的代码编写一个单元测试,它如下所示: public function test() { MYFACADE::doSomething(); } 在单元测试中,我试图模拟facade调用: MYFACADE::shouldReceive('doSomething') ->once() ->andReturn(false); 唯一的问题是,当Laravel试图为MYFACADE创建Underground类的实例时,它当然会运行构造函
public function test() {
MYFACADE::doSomething();
}
在单元测试中,我试图模拟facade调用:
MYFACADE::shouldReceive('doSomething')
->once()
->andReturn(false);
唯一的问题是,当Laravel试图为MYFACADE
创建Underground类的实例时,它当然会运行构造函数,并且就在这里,是硬编码的数据库连接调用。因此,在不更改facade并从facade类的构造函数中删除数据库连接的情况下,有没有办法在不运行facade构造函数的情况下模拟facade调用
更新:
设置的其余部分:
门面类
class MyFacade extends Facade
{
protected static function getFacadeAccessor()
{
return 'myfacade';
}
}
app.php
$app->register(App\Providers\MyServiceProvider::class);
class_alias('App\Facades\MyFacade', 'MYFACADE');
服务提供者:
class MyServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind('myfacade', function()
{
return new myClasThatDoesSomething();
});
}
}
facade使用的底层类
class myClasThatDoesSomething
{
public function __construct()
{
// opens db connection here
}
public function doSomething()
{
}
}
使用facade的示例类:
class TestClass
{
public function testMethod()
{
$returnValue = MYFACADE::doSomething();
return $returnValue;
}
}
检查testMethod()是否返回“testValue”的单元测试
MYFACADE::shouldReceive('doSomething')
->once()
->andReturn('testValue');
$instance = new TestClass();
$value = $instance->testMethod();
$this->assertEquals('testValue', $value);
首先是:
Facades为应用程序服务容器中可用的类提供“静态”接口
请确保您的MYFACADE
遵循此模式。没有空间容纳构造函数、数据库等。如果您测试MYFACADE::doSomething()
您应该模拟函数正在使用的所有其他类
其次,下面的代码
MYFACADE::shouldReceive('doSomething')
->once()
->andReturn(false);
模拟facade本身,以测试使用的其他内容MYFACADE::doSomething()
。它应该返回一个mockry
实例,该实例在测试中调用MYFACADE::doSomething()
时返回false
编辑:
Laravel的Facade模拟实现实例化了底层类,它允许使用精简构造函数测试服务。虽然这是最好的做法,但并不总是能够做到。假设您无法从构造函数中移动DB连接逻辑,最好是手动模拟服务:
public function testTestMethod()
{
MYFACADE::swap(\Mockery::mock()
->shouldReceive('doSomething')
->once()
->andReturn('testValue')
->getMock()
);
$instance = new \App\TestClass();
$value = $instance->testMethod();
$this->assertEquals('testValue', $value);
}
关于第二部分,你是对的,我实际上在测试其他东西,所以它在这种情况下工作。我所说的构造函数部分实际上是,为其创建外观的类的构造函数。因此,当Laravel为Facade定义绑定时,它将创建基础类的新实例。在该类中是单元测试中不必要的数据库调用。@如果您的外观实例化该类而不是从容器中获取实例,那么除了修复代码之外,您什么也做不了。TDD方法解决了这个问题。如果您希望对代码进行单元测试,则需要编写可测试代码。如果您在问题中添加代码示例,我很乐意展示如何实现这一点。我的服务提供商在register方法()中包含了这一点:
$this->app->bind('myfacade',function(){return new myClassThatDoThings();})
并且在myclassthatthings
构造函数中是有问题的数据库调用。遗憾的是,我无法在单元测试中以某种方式替换这个myclassthatthings
对象。将服务提供商称为facade;)是一种耻辱这样命名并不能使它成为一个门面。我看不出你的doSomething
方法在哪里,老实说,代码示例在注释格式中几乎不可读。你能用你要测试的代码的例子来编辑实际的问题吗?好的,我编辑了这个问题,我想它无处不在。请记住,它并不包含真正的逻辑,只是足够让我了解我要做什么。谢谢