【发布时间】:2019-04-21 00:10:42
【问题描述】:
我正在尝试模拟 a class 以防止它不得不调用 3rd 方 api。但是在设置模拟时,它似乎并没有影响控制器的动作。我确实尝试通过手动创建Request- 和OEmbedController-classes 的实例来替换$this->postJson()。 create()-method 被调用,但我收到来自 Mockery 的错误,它不是。
我在这里做错了什么?
错误:
Mockery\Exception\InvalidCountException : 来自 Mockery_2_Embed_Embed 的方法 create() 应该被准确调用 1 次,但被调用 0 次。
测试:
class OEmbedTest extends TestCase
{
public function tearDown()
{
Mockery::close();
}
/**
* It can return an OEmbed object
* @test
*/
public function it_can_return_an_o_embed_object()
{
$url = 'https://www.youtube.com/watch?v=9hUIxyE2Ns8';
Mockery::mock(Embed::class)
->shouldReceive('create')
->with($url)
->once();
$response = $this->postJson(route('oembed', ['url' => $url]));
$response->assertSuccessful();
}
}
控制器:
public function __invoke(Request $request)
{
$info = Embed::create($request->url);
$providers = $info->getProviders();
$oembed = $providers['oembed'];
return response()
->json($oembed
->getBag()
->getAll());
}
【问题讨论】:
-
不需要测试嵌入包;已经是tested了,对吧?
-
是的,所以我的想法是模拟该类的响应。
-
提示:您可以将
__invoke方法重命名为handle,它看起来会更好。您正在 (invoke) 方法中创建 Embed 的一个实例;没有模拟,那是无法测试的。我个人避免嘲笑任何东西并诉诸存根/假类等。我建议让 Laravel 在它到达控制器之前构建/创建/实例化 Embed 对象。这意味着创建一个服务提供者,它将负责为您实例化 Embed 对象,并可能将其放置在$request本身中。请添加有关您正在访问的路线的更多信息。 -
所以你基本上是说我应该依赖注入类?喜欢
$this->app->bind()。当然这是可能的,但如果没有它,它不应该是可能的吗?因为那时我需要一个接口等,这对于这个小测试来说感觉很麻烦。 -
你不需要接口,直接使用
->bind(Embed\Embed::class, function($app){ return Embed\Embed::create($app['request']->url); });现在不知道create被调用后会发生什么。但是在控制器中你现在可以使用$info = resolve(Embed\Embed::class);显然,您需要检查请求是否具有 url 参数等(在绑定闭包中执行此操作)。现在在测试setUp你需要重新绑定它,更多信息请阅读stackoverflow.com/questions/50262576/…