如何模拟Eloquent模型的静态方法?

Zed*_*Zed 10 unit-testing laravel eloquent mockery

我在我的代码中有这样一行:

ModelName::create($data);
Run Code Online (Sandbox Code Playgroud)

其中ModelName只是一个Eloquent模型.有没有办法在单元测试中模拟这个调用?我尝试过:

$client_mock = \Mockery::mock('Eloquent','App\Models\ModelName');
$client_mock->shouldReceive('create')
            ->with($data)->andReturns($returnValue);
Run Code Online (Sandbox Code Playgroud)

但它不起作用.

Mar*_*łek 13

你应该做这样的事情:

$client_mock = \Mockery::mock('overload:App\Models\ModelName');
$client_mock->shouldReceive('create')->with($data)->andReturn($returnValue);
Run Code Online (Sandbox Code Playgroud)

我们正在使用,overload:因为你不想将mock传递给某个类,但是如果它被硬编码到某些类中,你也想使用它.

除了你的测试类(就在之前class),你应该添加:

/**
 * @runTestsInSeparateProcesses
 * @preserveGlobalState disabled
 */
Run Code Online (Sandbox Code Playgroud)

为了避免这个类已经加载的错误(它可能在单个测试中没有它,但是当你运行多个测试时可能不会).

您可能会阅读Mocking hard dependencies以获取有关它的详细信息.

UPDATE

在某些情况下,可能无法使用此方法模拟类.在这些情况下,您可以创建普通的mock(不带overload)并将其注入服务容器,如下所示:

App::instance('\App\Models\ModelName', $client_mock); 
Run Code Online (Sandbox Code Playgroud)

  • 模拟公共静态方法调用时,应使用“ alias:App \ Models \ ModelName”,而不应使用“ overload:\ Models \ ModelName”。“ overload”用于拦截和模拟类实例化(例如new class()),而“ alias”则用于公共静态方法(Class :: method)。 (2认同)