如何在Laravel 5软件包中的测试中模拟接受标头?

2022-08-30 18:37:20

我目前正在构建一个Laravel包,该包通过Macros注入新方法。我正在注入的方法已经完成,预计可以很好地工作,但我也想在发布之前对其进行测试。Illuminate\Http\Request

我的测试要求我更改请求的标头,以便我查看测试是否通过。因此,我执行了以下操作来模拟请求:Accept

// package/tests/TestCase.php

namespace Vendor\Package;

use Illuminate\Http\Request;
use Orchestra\Testbench\TestCase as Orchestra;

abstract class TestCase extends Orchestra
{
    /**
     * Holds the request
     * @var Illuminate\Http\Request
     */
    protected $request;

    /**
     * Setup the test
     */
    public function setUp()
    {
        parent::setUp();

        $this->request = Request::capture();

        $this->request->headers->set('Accept', 'application/x-yaml');
    }
}

然后在我的测试中,我使用我正在注入的方法,它总是返回false,因为标头未设置为。Request$this->request->wantsYaml()Acceptapplication/x-yaml

class RequestTest extends TestCase
{
    /** @test */
    public function it_should_return_a_bool_if_page_wants_yaml_or_not()
    {
        dump($this->request->wantsYaml()); // Return false

        $this->assertTrue($this->request->wantsYaml()); // It fails!
    }
}

如何在Laravel软件包开发中的测试中继续模拟标头?


编辑

这是我的班级YamlRequest

use Illuminate\Http\Request;
use Illuminate\Support\Str;

class YamlRequest extends Request
{
    /**
     * Acceptable content type for YAML.
     * @var array
     */
    protected $contentTypeData = ['/x-yaml', '+x-yaml'];

    /**
     * Determine if the current request is asking for YAML in return.
     *
     * @return bool
     */
    public function wantsYaml()
    {
        $acceptable = $this->getAcceptableContentTypes();

        // If I dd($acceptable), it comes out as empty during tests!

        return isset($acceptable[0]) && Str::contains($acceptable[0], $this->contentTypeData);
    }
}

因此,我必须模拟“接受”,才能查看我的方法是否按预期工作。wantsYaml


答案 1

一个部分模拟的对象将允许你测试你的,而无需在Laravel的对象中测试辅助方法。换句话说,您真正需要知道的是您的宏是否正常工作。您无需测试是否可以构造 a 以及是否可以设置其标头。Illuminate\Http\Request::macroIlluminate\Http\RequestRequest

在下面的测试中,我将使用 Mockery 设置对象的“部分”模拟版本。YamlRequest

当我们只需要模拟一个对象的多个方法时,部分模拟是有用的,其余的可以自由地响应正常(即实现)的调用。

请参阅模拟文档,创建部分模拟

部分模拟将允许我们从Laravel的对象模拟方法,同时让你的宏像在生产环境中一样自由运行。Request

use YamlRequest;
use \Mockery;

class RequestTest extends TestCase
{
    public function setUp()
    {
        parent::setUp();

        $this->request = Mockery::mock(YamlRequest::class)->makePartial();
    }

    public function test_that_wants_yaml_returns_true_given_x-yaml_accept_header()
    {
        /**
         *  This line allows you to control the return value of
         *  Illuminate\Http\Request::getAcceptableContentTypes while your macro
         *  is running.
         */
        $this->request->allows(
            [
                'getAcceptableContentTypes' => ['application/x-yaml', 'text/html']
            ]
        );

        $this->assertTrue($this->request->wantsYaml());
    }

    public function test_that_wants_yaml_returns_false_given_json_accept_header()
    {
        $this->request->allows(
            [
                'getAcceptableContentTypes' => ['application/json', 'text/html']
            ]
        );

        $this->assertFalse($this->request->wantsYaml());
    }
}

答案 2

如果你使用单元测试来测试应用,则有一个预构建的 laravel assertHeader()assertHeaderMissing() 函数可能会对你有所帮助。请参阅此处的官方文档。这是从文档中获取的代码片段,

$response->assertHeader($headerName, $value = null);
$response->assertHeaderMissing($headerName);

推荐