reedware/container-testcase

启用空服务容器的单元测试。

v1.1.0 2023-07-24 13:20 UTC

This package is auto-updated.

Last update: 2024-09-24 15:43:18 UTC


README

Laravel Version Automated Tests Coding Standards Code Coverage Static Analysis Latest Stable Version

此软件包可启用空服务容器的单元测试。

目录

简介

我是一位单元测试的坚定支持者,但在为 Laravel 开发软件包时,我经常发现自己需要在单元测试中使用服务容器。此软件包仅实现了我多年来一直遵循的模板,但从未在共享位置中定义。

这种测试方法使测试用例保持轻量级,因为您无需启动整个 Laravel 应用程序,但仍可获得一些对测试作为软件包开发一部分创建的服务所必需的生活质量功能。

安装

使用 Composer 安装此软件包

composer require reedware/container-testcase --dev

请注意 --dev 标志。此软件包旨在用于测试。因此,它只应在开发设置中需要。

接下来,您有两个选项:扩展或特性。

1. 扩展

将测试用例更改为从 Reedware\ContainerTestCase\ContainerTestCase 扩展。

use Reedware\ContainerTestCase\ContainerTestCase;

class TestCase extends ContainerTestCase
{
    /* ... */
}

2. 特性

ServiceContainer 特性添加到测试用例中。

use PHPUnit\Framework\TestCase as BaseTestCase;
use Reedware\ContainerTestCase\ServiceContainer;

class TestCase extends BaseTestCase
{
    use ServiceContainer;
}

请注意,特性会覆盖 setUp()tearDown() 方法。如果您有自己的定义,您需要调用特性提供的 setUp/tearDown 功能。

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

    $this->setUpServiceContainer();
}

protected function tearDown(): void
{
    $this->tearDownServiceContainer();

    parent::tearDown();
}

用法

1. 服务提供者

如果您正在编写绑定到服务容器的软件包,那么您很可能有一个服务提供者。您希望在设置过程中注册您的服务提供者

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

    $this->registerServiceProvider(MyServiceProvider::class);
}

您可以为引导过程执行类似操作

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

    $this->bootServiceProvider(MyServiceProvider::class);
}

boot() 方法中的任何依赖项都将从服务容器中注入,与 Laravel 框架的方式相同。

2. 应用实例

测试中的应用程序实例与 Laravel 框架提供的不相同。提供的应用程序实例提供了完整的容器功能,但默认情况下在非容器方法(例如 $this->app->version())上抛出异常。如果您需要在服务提供者中使用这些方法,可以向应用程序实例提供期望,因为它还充当部分模拟实例。

/** @test */
public function it_bails_on_production(): void
{
    $this->app
        ->shouldReceive('environment')
        ->withNoArgs()
        ->once()
        ->andReturn('production');

    $this->registerServiceProvider(MyServiceProvider::class);

    $this->assertFalse($this->app->bound(MyService::class));
}

3. 服务容器

应用程序实例充当您的服务容器。类似于 Laravel 的功能测试,测试用例上的一些模拟和容器助手作为方法可用

Make

使用容器创建指定服务的全新实例。是 $this->app->make(...) 的别名。

用法

$service = $this->make(MyService::class);

Mock

创建指定服务的模拟,并将其绑定到容器。

用法

$mock = $this->mock(MyService::class, function (MockInterface $mock) {
    $mock
        ->shouldReceive(...)
        ->...
});

$mock = $this->mock(MyService::class);

$mock
    ->shouldReceive(...)
    ->...

注意:此方法将模拟实例绑定到 MyService::class。如果您只想绑定未绑定到容器的模拟服务,请使用 Mockery::mock(MyService::class)

Mock As

创建指定服务的模拟,并将其绑定到容器下的给定别名。$this->mock(...) 方法将使用其类名绑定服务到容器。但是,如果您希望使用不同的名称绑定它,请使用 $this->mockAs(...)

用法

$mock = $this->mockAs(MyService::class, 'acme.service', function (MockInterface $mock) {
    /* ... */
});

现在从容器解析 acme.service 的任何内容都将接收您的模拟服务。

Mock Config

对于包含配置文件且希望对其服务进行单元测试的软件包,您可以使用 $this->mockConfig(...) 将基本配置存储库绑定到容器,该存储库产生提供的值。

用法

$this->mockConfig([
    'my-package' => [
        'setting-1' => 'foo'
    ]
]);

config('my-package.setting-1'); // "foo"

4. 基础助手

Laravel 框架提供了一些辅助方法,可以帮助您与服务容器进行交互。本软件包复制了这些方法的一部分,以便您获得相同的生活质量,而无需在您的软件包中包含整个 Laravel 框架。不用担心,如果您决定使用整个 Laravel 框架,Laravel 的辅助方法将优先于这些方法。

断言

Laravel 的测试用例包含一些基本的断言,这些断言在单元测试中非常有用。这些断言也被包含在内。

1. 数组子集

断言一个数组包含指定的子集。

用法

/** @test */
public function it_has_some_attributes(): void
{
    $myObject = $this->newMyObject();

    $this->assertArraySubset([
        'foo' => 'bar'
    ], $myObject->toArray());
}

Pest

如果您正在使用 Pest,本软件包提供了一些额外的扩展。

1. 期望

本软件包提供的针对 PHPUnit 的断言也有自己的 Pest 预期口味。

  • PHPUnit => Pest
  • $this->assertArraySubset($subset, $actual) => expect($actual)->toContainArraySubset($subset)

2. Pest 助手

如果您专注于软件包开发,并且想使用 Pest,请留意 Laravel Pest 插件pestphp/pest-plugin-laravel)。该软件包需要整个 Laravel 框架,这在软件包开发中并不总是最佳选择。因此,本软件包包括了 Laravel Pest 插件提供的辅助方法的一部分,特别是那些与服务容器交互的方法。

  • swap($abstract, $instance)
  • instance($abstract, $instance)
  • mock($abstract, $mock = null)
  • mockAs($abstract, $alias, $mock = null)
  • partialMock($abstract, $mock = null)
  • spy($abstract, $mock = null)