为啥 Mockery 无法为我的模型创建别名

Posted

技术标签:

【中文标题】为啥 Mockery 无法为我的模型创建别名【英文标题】:Why Mockery is unable to make an alias of my model为什么 Mockery 无法为我的模型创建别名 【发布时间】:2020-09-01 03:58:04 【问题描述】:

我有以下型号:

namespace App\Model;

use Illuminate\Database\Eloquent\Model;

class MyModel extends Model

    public static function foo():bool
    
      return true;
    

为此,我制作了以下控制器:


namespace App\Controler;

use App\Model\Foo;

class MyController

   public function bar()
   
      $value=MyModel::foo();
      if($value)
        return "OK"; 
      
      throw new \Exception("Foo not true");
   


我想测试我的控制器:

namespace Tests;

use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use App\Model\MyModel;
use Mockery;

class MyControllerTest extends BaseTestCase

   public function testBar()
   
      $mock=Mockery::mock('alias:'.MyModel::class);
      $mock->shouldReceive('foo')->andReturn(false);
      /// Rest of thest here
   

但是一旦我运行我的测试,我就会收到以下错误:

phpUnit 7.5.20 by Sebastian Bergmann and contributors.

E                                                                   1 / 1 (100%)

Time: 1.62 seconds, Memory: 14.00 MB

There was 1 error:

1) Tests\MyControllerTest::testBar
Mockery\Exception\RuntimeException: Could not load mock App\Model\MyModel, class already exists

/var/www/html/vendor/mockery/mockery/library/Mockery/Container.php:226
/var/www/html/vendor/mockery/mockery/library/Mockery.php:118
/var/www/html/tests/MyControllerTest.php:20

ERRORS!
Tests: 1, Assertions: 0, Errors: 1.

为了减轻https://***.com/a/53266979/4706711 中看到的错误,我尝试了:

namespace Tests;

use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use App\Model\MyModel;
use Mockery;

class MyControllerTest extends BaseTestCase


  /**
   * @runInSeparateProcess 
   * @preserveGlobalState disabled
   */
   public function testBar()
   
      $mock=Mockery::mock('alias:'.MyModel::class);
      $mock->shouldReceive('foo')->andReturn(false);
      /// Rest of thest here
   

但我仍然遇到同样的错误。

根据@mohammad.kaab 的回答,我尝试了以下方法:

namespace Tests;

use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use App\Model\MyModel;
use Mockery;

class MyControllerTest extends BaseTestCase


  /**
   * @runInSeparateProcess 
   * @preserveGlobalState disabled
   */
   public function testBar()
   
      $this->app->instance(MyModel::class, \Mockery::mock(MyModel::class, function($mock)
            $mock->shouldReceive('foo')->andReturn(true);
        ));
        $myModel = $this->app->make(MyModel::class);
        dd($myModel::foo()); // should return true
   

虽然它不能工作,因为\Mockery::mock 模拟了一个实例,而不是模拟类本身。因此我尝试了以下方法:

   public function testBar()
   
      $mock=Mockery::mock('alias:'.MyModel::class);
      $mock->shouldReceive('foo')->andReturn(false);
      /// Rest of thest here
   

而且对我没有用。

【问题讨论】:

$mock=Mockery->mock( 这部分在我看来不是一个有效的语法。您要么创建模拟实例,要么调用静态方法?您还缺少导入中的分号。 我修正了它的错字。 这能回答你的问题吗? Mockery fails with 'Could not load mock ... class already exists' when running with --code-coverage 不,如您所见,我尝试了但没有为我工作。 导入use Mockery时的那个分号呢?这个问题只在这里丢失吗? 【参考方案1】:

也许你可以使用这个代码

$this->app->instance(MyModel::class, \Mockery::mock(MyModel::class, function($mock)
            $mock->shouldReceive('foo')->andReturn(true);
        ));
        $myModel = $this->app->make(MyModel::class);
        dd($myModel::foo()); // should return true

【讨论】:

它不起作用,原因如下: 1. 我需要一个别名,但使用别名的方法仍然不起作用。我得到了同样的错误。我还需要模拟一个我不想创建它的实例的 STATIC 方法。

以上是关于为啥 Mockery 无法为我的模型创建别名的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Xcode 会为我的模型类的布尔属性生成 NSNumber 属性?

模型上的 Laravel PHP 别名?

为啥我会通过 Mockery 获得 NoMatchingExpectationException?

Laravel 5 - 使用 Mockery 模拟 Eloquent 模型

使用 Mockery Eloquent 模型模拟 Laravel

为啥我的表单创建一个新的模型对象而不是修改一个?