thatsus/laravel-better-bind

Laravel自动化测试中更好的绑定功能

v1.0.1 2018-09-17 16:06 UTC

This package is auto-updated.

Last update: 2024-09-18 08:50:25 UTC


README

Laravel/Lumen 5+ 中的更好绑定功能,用于自动化测试。

为什么Better Bind更优秀

  1. 它比Laravel内置选项更简洁。
  2. 它可以保护你免受缺失构造函数参数的影响。
  3. 你可以选择检查构造函数参数的正确性。

使用mocks在Laravel中进行自动化测试意味着通过应用程序的 bind 方法注入对象。

这可能会带来一些缺点。

  • App::bind 在Laravel中很冗长。
  • App::bind 并不测试一个对象是否使用了正确的参数进行实例化。

Better Bind 提供了一种语法友好的机制,以验证构造函数参数是否与目标类匹配。

缺少必要的参数会导致断言失败。

多余的参数会导致断言失败。

类型错误的参数会导致断言失败。

它可以是一行代码。

Better Bind 还提供了一种方法来捕获构造函数参数,以便你可以对它们运行自己的断言。

安装

composer require thatsus/laravel-better-bind
class TestCase
{
    use \ThatsUs\BetterBind;

    ...
}

示例测试

在这个例子中,我们期望 Dog::bark 方法创建一个 Sound 对象,将自身作为构造函数的 $animal 参数的值。

首先,我们使用Better Bind的 betterInstance 方法提供mock给代码。然后我们捕获 $params 参数,并在最后检查它是否包含我们期望的参数值。

class DogTest extends TestCase
{
    public function testBark()
    {
        $mock = Mockery::mock(Sound::class);
        $mock->shouldReceive('emit')
            ->once();
        $this->betterInstance(Sound::class, $mock, $params);

        $dog = new Dog();
        $dog->bark();

        $this->assertEquals(['animal' => $dog], $params);
    }
}
class Sound
{
    public function __construct(Animal $animal)
    {
        // ...
    }
}

通过代码

Gallant 使用正确的参数编写了正确的构造函数代码。

class Dog
{
    public function bark()
    {
        App::makeWith(Sound::class, ['animal' => $this])->emit();
    }
}

失败代码1

Goofus 忘记包含构造函数参数的名称。

class Dog
{
    public function bark()
    {
        App::makeWith(Sound::class, [$this])->emit();
    }
}
1) DogTest::testBark
Required parameter `animal` not provided to class constructor for `Sound`

失败代码2

现在Goofus意外地为构造函数添加了额外的参数。

class Dog
{
    public function bark()
    {
        App::makeWith(Sound::class, ['animal' => $this, 'volume' => 'loud'])->emit();
    }
}
1) DogTest::testBark
Extra parameters provided to class constructor for `Sound`: `volume`

失败代码3

Goofus意外地传递了一个字符串。这是 $animal 参数的错误类型。

class Dog
{
    public function bark()
    {
        App::makeWith(Sound::class, ['animal' => 'this'])->emit();
    }
}
1) DogTest::testBark
Required parameter `animal` for `Sound` is a `string`, but a `Animal` is expected.

方法

betterInstance($signature, $object, [&$params = []])

  • $signature - 字符串,在 makeWith 调用中请求的类名或其他字符串。
  • $object - 混合类型,从 makeWith 调用返回的值。
  • $params - 可选的,当 makeWith 被调用时,此变量将用发送到 makeWith 的参数更新,以便测试代码可以对这些参数进行断言。

如果 $signature 是一个不指向现有类的字符串,则不会对参数运行断言。

betterBind($signature, $closure, [&$params = []])

  • $signature - 字符串,在 makeWith 调用中请求的类名或其他字符串。
  • $closure - 当 makeWith 被调用时将调用的闭包。将返回从 makeWith 返回的值。参数将是 $app,应用程序对象,以及 $params,发送到 makeWith 的参数数组。
  • $params - 可选的,当 makeWith 被调用时,此变量将用发送到 makeWith 的参数更新,以便测试代码可以对这些参数进行断言。

如果 $signature 是一个不指向现有类的字符串,则不会对参数运行断言。

betterBind(...)->ignoreParameters($param1, $param2, ...)

允许Laravel提供命名的参数。不要检查给定的参数名称是否由 makeWith 调用提供。

  • $paramN - 字符串,参数的名称

我不确定。我能不能不用Better Bind做这个?

你可以做一些相同的事情,而不使用这个库。

比较以下测试版本。

class DogTest extends TestCase
{
    public function testBark()
    {
        $mock = Mockery::mock(Sound::class);
        $mock->shouldReceive('emit')
            ->once();
        $this->betterInstance(Sound::class, $mock, $params);

        $dog = new Dog();
        $dog->bark();

        $this->assertEquals(['animal' => $dog], $params);
    }
}
class DogTest extends TestCase
{
    public function testBark()
    {
        $mock = Mockery::mock(Sound::class);
        $mock->shouldReceive('emit')
            ->once();
        App::bind(Sound::class, function ($app, $bind_params) use (&$params, $mock) {
            $params = $bind_params;
            return $mock;
        });

        $dog = new Dog();
        $dog->bark();

        $this->assertEquals(['animal' => $dog], $params);
    }
}

不使用Better Bind的版本的明显缺点是,有额外的行,其中一行非常冗长。这里的秘密额外缺点是,没有测试来确保对真实 Sound 类构造函数的要求得到满足。

如果你编写了 "失败代码1" 中的代码会发生什么?

class Dog
{
    public function bark()
    {
        App::makeWith(Sound::class, [$this])->emit();
    }
}

Laravel会检测到Sound构造函数的类型提示了一个Animal对象。但是'animal'元素不在params中,所以Laravel会创建一个新的Animal对象来完成任务。测试不会失败。

使用Better Bind,会检测到缺失的值,测试将失败。

如果您希望Laravel自己填充一个新的Animal对象,可以添加->ignoreParameters('animal')

兼容性

我们认为此代码与Laravel 5+和Lumen 5+的所有版本兼容,但进行测试是一项繁琐的工作,因为5.4中将make更改为makeWith,只是为了让 everyone 感到困惑。给我们留言并告诉我们它有多好,以及您正在使用哪个版本的Laravel。

贡献

如果您发现了一个错误或想要为代码或文档做出贡献,您可以通过提交一个问题或一个拉取请求来帮助。

许可

MIT