使用桩件 (Stub) 解决 Laravel 单元测试中的依赖
很早就知道有单元测试的概念,也曾尝试过,但是一直对单元测试的概念和方法,比较模糊。在听了 @vimac 大神的讲堂 PHP单元测试与测试驱动开发 后,慢慢地对单元测试和 PHPUnit 的认识清晰了起来,也开始慢慢地去实践单元测试。 Laravel 中的依赖我们都知道,Laravel 使用了 IoC,各个模块之间也因此解耦了。而正是因为这一点,我们在 Laravel 中编写单元测试的时候,变得更加轻松了。 举个栗子考虑以下场景。我们在开发中,可能会在控制器和模型之间加一个 假设我们现在有这样一个 Repository,里面记录了商品的信息,我们想要在 Controller 中获取某件商品信息,然后执行一些业务逻辑。 Class GoodRepository { public function getGoodById($goodId) { // TODO: Get good by its id. } } class GoodController extends Controller { public function show($id,GoodRepository $goodRepository) { // TODO: Do something with good info from that repository. } } // In route/api.php Route::get('/api/good/{id}','GoodController@show'); // Create a RepositoriesServiceProvider in Provider/RepositoriesServiceProvider.php。 // And inject the GoodRepository into Container. class RepositoriesServiceProvider extends ServiceProvider { public function boot() { } public function register() { $this->app->singleton(GoodRepository::class); } } 好了,我们可以发现, 在 Laravel,提供了 桩件
这是 PHPUnit 文档上 的解释。那我的理解呢,所谓的桩件,就是模拟一个依赖的类的行为,使得这个行为所做的事情在我们自己的掌控之中。比如上面的这种情况,我们希望模拟 在 Laravel 中使用桩件我们通过 class GoodControllerTest extends TestCase { public function testShow() { $data = []; // The data returns from GoodRepository::getGoodById. $stub = $this->createMock(GoodRepository::class); $stub->method('getGoodById')->will($this->returnValue($data)); $this->app->singleton(GoodRepository::class,function () use ($stub) { return $stub; }); $response = $this->get('/api/good/1'); // Some assertions. } } 我们通过在这里将桩件 如果我们在这里不使用桩件,而是直接依赖外部(数据库)中的数据,那么如果 id 为 1 的数据被删除了,我们是不是就要改成 2 了呢?我们是不是就要重新计算数据了匹配断言了呢?这样的测试,可靠性便大大降低。 后记任何一个可靠的系统,单元测试都是必不可少的。庆幸的是,PHPUnit 帮我们提供了好用的单元测试。本文所讲的,也只是 PHPUnit 的九牛一毛。而我自己也在慢慢摸索慢慢实践中。与君共勉。 最后还是推荐去听一下 @vimac 的讲堂 PHP单元测试与测试驱动开发,受益匪浅。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |