thatsus / laravel-better-bind
Laravel自动化测试中更好的绑定功能
Requires
- php: >=7.0.0
- illuminate/support: ^5.0,<5.6
Requires (Dev)
- orchestra/testbench: ~3.0
- php-mock/php-mock-mockery: ^1.1
- phpunit/phpunit: ~5.7
This package is auto-updated.
Last update: 2024-09-18 08:50:25 UTC
README
Laravel/Lumen 5+ 中的更好绑定功能,用于自动化测试。
为什么Better Bind更优秀
- 它比Laravel内置选项更简洁。
- 它可以保护你免受缺失构造函数参数的影响。
- 你可以选择检查构造函数参数的正确性。
使用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。
贡献
如果您发现了一个错误或想要为代码或文档做出贡献,您可以通过提交一个问题或一个拉取请求来帮助。