laravel-5 - 在工匠命令中使用的接口上使用链接的部分模拟
问题描述
我正在尝试在 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
),但是在这种情况下,虽然模拟$second_repository_mock->getExternalClient()
正确,但测试仍然期望对$second_repository_mock->getSomeValue()
. 由于$second_repository_mock
设置为部分模拟,我不明白为什么它仍在寻找要模拟的所有函数。
如果我删除该$external_client_mock
部分并完全模拟$second_repository_mock
与 artisan 命令工作直接相关的测试,但是我想测试触发的事件getSomeValue()
是否从 artisan 命令正确处理,如果我不能这样做,我就无法做到使用部分模拟。
有没有人知道为什么这不起作用?
解决方案
您正在尝试模拟一个没有意义的界面。接口没有要使用的具体实现。这会导致错误的代码。只需模拟您的存储库,它就会起作用。
编辑
刚刚使用以下重构运行测试,它们变为绿色:
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
.
推荐阅读
- vue.js - 根据当前语言加载不同的 scss 文件 - nuxt
- javascript - 使用 JavaScript 检查 JSON 值/数组是否存在并在表格中显示数据
- java - 如何使用 crt 和 pkcs8_key 建立 http(s) url 连接 - java
- python - 如何为我的 html 烧瓶网站制作下载链接?
- docker - 即使已拉取所需的 docker 映像,为什么还需要 `--cache-from`?
- javascript - React Material UI:使用 withStyles 和 React Router 时 this.props 未定义
- postgresql - postgres 解析 json 以找到兼容的条目
- c# - 如何在 ViewData 中动态显示来自控制器的数据作为集合 Highcharts
- reactjs - 反应 setState 以切换布尔值不起作用
- javascript - Project PWA JS Grid - 如何过滤下拉多值控件中显示的引用表值