Laravel-如何为此编写测试?

时间:2019-06-04 19:44:17

标签: laravel

对于测试来说还很新,无法解决。如何防止Spatie的软件包在此处实际运行。我只想伪造一个回应。

示例控制器:

<?php

namespace App\Http\Controllers;
use Spatie\SslCertificate\SslCertificate;

class SSLController extends Controller {

 function getIsValid(){

     $certificate = SslCertificate::createForHostName('https://example.url');

     return $certificate->isValid();

    }
}

示例测试:

<?php 

namespace Tests\Unit;

use Tests\TestCase;
use Spatie\SslCertificate\SslCertificate;

class SSLCheckPlugInTest extends TestCase {

    public function it_returns_the_ssl_certs_status(){

         $this->mock(SslCertificate::class,function($mock){
            $mock->shouldReceive('createForHostName')->once();
        });

        $response = $this->get('/path-that-calls-the-controller-above');

    }
}

此示例代码仍然触发包中的实际调用(对example.url)并返回:

Mockery\Exception\InvalidCountException: Method createForHostName(<Any Arguments>) from Mockery_2_Spatie_SslCertificate_SslCertificate should be called
 exactly 1 times but called 0 times.

我觉得我确实缺少一些明显的东西。

编辑

@bishop建议只为该isValid方法编写一个模拟程序,但我不知道该怎么做。

2 个答案:

答案 0 :(得分:1)

Laravel的测试用例中的$this->mock()方法专门用于在Laravel的服务容器中模拟对象的实例。从文档中:

  

模拟要注入到您的对象中的对象时   通过Laravel服务容器的应用程序,您将需要绑定   将您模拟的instance作为实例绑定放入容器。

您可以直接使用Mockery模拟其他不会加载到服务容器中的类或实例。

我认为您应该同时模拟createForHostNameisValid方法。然后,测试的目的基本上仅仅是检查您的控制器方法是否返回给定的已知证书有效性。

您可以首先使用以下方法模拟要从SslCertificate返回的createForHostName实例:

$certificateMock = Mockery::mock('overload:Spatie\SslCertificate\SslCertificate');
$certificateMock->shouldReceive('isValid')->once()->andReturn(True);

我们是overloading上面的类,因此我们可以模拟该类的实例方法和静态方法。

然后,您可以模拟createForHostName方法以从上面返回模拟类的实例:

$certificateMock->shouldReceive('createForHostName')->once()->andReturn($certificateMock);

答案 1 :(得分:1)

模拟SslCertificate会很困难,因为您是静态使用它的。

相反,您应该将其注入到类(或方法)中。这样,Laravel的服务容器即可解决该问题,因此您可以对其进行模拟。

class SSLController extends Controller
{
    function getIsValid(SslCertificate $sslCertificate)
    {
        $certificate = $sslCertificate->createForHostName('https://example.url');

        return $certificate->isValid();
    }
}

class SSLCheckPlugInTest extends TestCase
{
    public function it_returns_the_ssl_certs_status()
    {
        $this->mock(SslCertificate::class, function ($mock) {
            $mock->shouldReceive('createForHostName')->once();
        });

        $response = $this->get('/path-that-calls-the-controller-above');
    }
}

现在,运行控制器后,它将检查容器中的SslCertificate,并找到您的模拟物并执行期望。