Php 使用Laravel/流明立面进行测试

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类的实例时,它当然会运行构造函

因此,我试图为一段使用facade的代码编写一个单元测试,它如下所示:

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
方法在哪里,老实说,代码示例在注释格式中几乎不可读。你能用你要测试的代码的例子来编辑实际的问题吗?好的,我编辑了这个问题,我想它无处不在。请记住,它并不包含真正的逻辑,只是足够让我了解我要做什么。谢谢