我正在尝试对Laravel 5.3中的一个工匠命令进行单元测试。该命令调用作为接口提供给命令构造函数的类中的函数。该接口调用另一个类中的函数。这是常规设置。
class MyCommand
{
public function __construct(MyRepositoryInterface $interface)
{
...
$this->interface = $interface;
...
}
public function fire()
{
$this->interface->useTheSecondClass();
}
}
class MyRepository implements MyRepositoryInterface
{
public function __construct(MySecondRepositoryInterface $second)
{
...
$this->second = $second;
...
}
public function useTheSecondClass()
{
$response = $this->second->getSomeValue();
}
}
class MySecondRepository implements MySecondRepositoryInterface
{
/**
* @return Some\External\Client
*/
public function getExternalClient()
{
....
return $external_client;
}
public function getSomeValue()
{
$client = $this->getExternalClient();
$something = $client->doSomething();
Event::fire('some event based on $something`);
return $something;
}
}
我正在尝试模拟MySecondRepository -> getExternalClient()
中返回的变量,以便我可以伪造一个外部API调用并使用伪造的数据来测试MySecondRepository -> getSomeValue()
和MyRepository -> useTheSecondClass()
的功能来自MyCommand
类。
public function testMyCommand()
{
$external_client_mock = Mockery::mock("Some\External\Client");
$external_client_mock->shouldReceive("doSomething")
->andReturn("some values");
$second_repository_mock = Mockery::mock("MySecondRepositoryInterface")
->makePartial();
$second_repository_mock->shouldReceive("getExternalClient")
->andReturn($external_client_mock);
$resource = new MyRepository($second_repository_mock);
$this->app->instance("MyRepositoryInterface", $resource);
$class = App::make(MyCommand::class);
$class->fire();
...
}
我已经成功使用了这个完全相同的模拟链来直接测试$resource
变量(例如,直接测试$resource->useTheSecondClass()
,而不是通过MyCommand
进行测试),但是在这种情况下,{{ 1}}的模拟正确,测试仍然期望$second_repository_mock->getExternalClient()
会有模拟的期望。由于$second_repository_mock->getSomeValue()
设置为部分模拟,所以我不明白为什么它仍在寻找所有要模拟的函数。
如果我删除$second_repository_mock
部分并完全模拟$external_client_mock
我的与artisan命令工作直接相关的测试,但是我想测试$second_repository_mock
中触发的事件是否已处理正确地使用了artisan命令,如果我不能使用部分模拟,那是无法做到的。
有人对为什么它不起作用有任何见识吗?
答案 0 :(得分:0)
您正在尝试模拟没有意义的接口。接口没有要使用的具体实现。这导致错误的代码。只需模拟您的存储库,它就会起作用。
编辑
只需使用以下重构运行测试,它们就会变为绿色:
public function testMyCommand() // phpcs:ignore
{
$external_client_mock = \Mockery::mock("App\Client");
$external_client_mock->shouldReceive("doSomething")
->andReturn("some values");
$second_repository_mock = \Mockery::mock("App\MySecondRepository[getExternalClient]")
->shouldIgnoreMissing();
$second_repository_mock->shouldReceive("getExternalClient")
->andReturn($external_client_mock);
$resource = new MyRepository($second_repository_mock);
$this->app->instance("App\MyRepositoryInterface", $resource);
$class = \App::make(\App\MyClass::class);
$class->fire();
}
唯一的主要区别是倒数第二行有App\MyCommand
,而不是App\MyClass
。