Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Laravel+嘲弄无效计数异常_Laravel_Mockery - Fatal编程技术网

Laravel+嘲弄无效计数异常

Laravel+嘲弄无效计数异常,laravel,mockery,Laravel,Mockery,我正在尝试模拟,以防止它不得不调用第三方API。但是在设置模拟时,它似乎不会影响控制器的操作。我确实尝试过通过手动创建Request和OEmbedController类的实例来替换$this->postJson。create方法正在被调用,但我从mockry收到一个错误,它不是 我做错了什么 错误: mockry\Exception\InvalidCountException:从mockry\u 2\u Embed\u Embed创建的方法应精确调用1次,但调用0次 测试: 控制器: publi

我正在尝试模拟,以防止它不得不调用第三方API。但是在设置模拟时,它似乎不会影响控制器的操作。我确实尝试过通过手动创建Request和OEmbedController类的实例来替换$this->postJson。create方法正在被调用,但我从mockry收到一个错误,它不是

我做错了什么

错误:

mockry\Exception\InvalidCountException:从mockry\u 2\u Embed\u Embed创建的方法应精确调用1次,但调用0次

测试:

控制器:

public function __invoke(Request $request)
{
    $info = Embed::create($request->url);

    $providers = $info->getProviders();

    $oembed = $providers['oembed'];

    return response()
        ->json($oembed
            ->getBag()
            ->getAll());
}

似乎您以错误的方式嘲笑嵌入类。如果您使用Laravel facade方法shouldReceive而不是创建类本身的模拟,则框架将为您将模拟放置在服务容器中:

Embed::shouldReceive('create')
    ->with($url)
    ->once();
而不是

Mockery::mock(Embed::class)
    ->shouldReceive('create')
    ->with($url)
    ->once();

还要注意,如果测试代码传递给mock的参数与使用$url学习mock的参数不同,那么mock会认为自己是未调用的。但是,调用未定义的方法时,您将收到另一个错误。

我在测试中使用此方法解决了此问题:

protected function setUp()
{
    parent::setUp();

    app()->instance(Embed::class, new FakeEmbed);
}
然后像这样解决它

$embed = resolve(Embed::class);
$embed = $embed->create($url);

您不需要测试嵌入包;它已经存在了,对吗?是的,所以我的想法是模拟该类的响应。提示:您可以重命名_invoke方法来处理它,这样看起来会更好。您正在invoke方法中创建嵌入的实例;没有嘲弄,这是不稳定的。我个人避免模仿任何东西,并求助于存根/伪类等。我建议让Laravel在嵌入对象到达控制器之前构建/创建/实例化它。这意味着创建一个服务提供者,负责为您实例化嵌入对象,并可能将其放入$request本身。添加更多关于您正在访问的路由的信息。那么您基本上是说我应该依赖注入类?比如$this->app->bind。当然这是可能的,但如果没有它,难道不可能吗?因为我需要一个接口,等等,这对于这个小测试来说很麻烦。你不需要接口,只要使用->bindebed\Embed::class,函数$app{return Embed\Embed::create$app['request']->url;};现在我不知道在create被调用之后发生了什么。但是在控制器中,您现在可以使用$info=resolvembed\Embed::class;显然,您需要检查请求是否有url参数等,并在绑定闭包中执行此操作。现在在测试设置中,您需要重新绑定它,有关更多信息,请阅读Embed类不是Facade。它的名称空间是Embed\Embed。那么您试图模拟一个静态方法?恐怕这行不通。我不知道不使用Facades就不能模拟静态方法。这实际上是模拟库的一个限制,而不是Laravel。立面仅提供对方法的静态访问;这并不意味着方法本身是静态的,事实上,据我所知,它们从来都不是静态的。所以实现可测试性的最简单方法是围绕它构建自己的代理类。。。它不使用静态方法。所以你创建了另一个类FakeEmbed进行模拟?是的,这是最简单的方法。
$embed = resolve(Embed::class);
$embed = $embed->create($url);