在 Lumen 测试中使用命名路由
发布日期:作者: Paul Redmond
在 Lumen 中编写测试时,我最近发现 route()
助手无法开箱即用地与测试一起使用。
我更喜欢定义命名路由并在我的测试中对它们进行请求。如果您遵循 Lumen 文档,您在测试中发出请求的典型方法如下所示
$this->json('GET', '/posts/1') ->seeJson(['title' => 'Hello World']);
使用路由助手,您的测试可能如下所示
public function testShowingAPost(){ $this->json('GET', route('posts.show', ['id' => 1])) ->seeJson(['title' => "Hello World"]);}
如果您运行上述测试,以下是 URL 将返回的内容
phpunitPHPUnit 6.4.4 by Sebastian Bergmann and contributors. .F 2 / 2 (100%) Time: 48 ms, Memory: 6.00MB There was 1 failure: 1) ExampleTest::testShowingAPostInvalid JSON was returned from the route. Perhaps an exception was thrown?
如果您仔细检查一下,您会看到问题
public function testShowingAPost(){ $this->json('GET', route('posts.show', ['id' => 1])); dd( $this->response->getContent(), route('posts.show', ['id' => 1]) ); $this->seeJson(['title' => "Hello World"]);}
有趣的是,路由看起来不太对,路由器返回的是 /
路由
phpunitPHPUnit 6.4.4 by Sebastian Bergmann and contributors. string(40) "Lumen (5.5.2) (Laravel Components 5.5.*)"string(16) "http://:/posts/1"
看起来请求的 localhost
部分没有设置,路由没有匹配。我们可以通过像 Laravel 一样引导请求来解决这个问题。
引导请求
当您在 Laravel 框架中运行测试时,项目包含 CreatesApplication
特性,它在设置期间被调用,进而引导应用程序的类。其中一个“引导器”是 SetRequestForConsole,它引导控制台的请求。
我们可以复制此功能,以便 Lumen 中的测试在设置时有一个引导的请求,但这需要我们做一些工作。
基本 TestCase 类最终会在设置期间调用 refreshApplication()
,进而调用 tests/TestCase.php
文件中定义的 createApplication()
。
createApplication()
方法返回应用程序,因此我们可以在此阶段引导请求,然后返回应用程序并将其分配给 $this->app
。
以下是 Lumen 附带的默认基本 TestCase
类的样子
<?php abstract class TestCase extends Laravel\Lumen\Testing\TestCase{ /** * Creates the application. * * @return \Laravel\Lumen\Application */ public function createApplication() { return require __DIR__.'/../bootstrap/app.php'; }}
打开 tests/TestCase.php
文件,并将其更新为以下内容,以复制 Laravel 的 SetRequestForConsole
<?php use Illuminate\Http\Request;use Laravel\Lumen\Testing\TestCase as BaseTestCase; abstract class TestCase extends BaseTestCase{ /** * Creates the application. * * @return \Laravel\Lumen\Application */ public function createApplication() { $app = require __DIR__.'/../bootstrap/app.php'; $uri = $app->make('config')->get('app.url', 'http://localhost'); $components = parse_url($uri); $server = $_SERVER; if (isset($components['path'])) { $server = array_merge($server, [ 'SCRIPT_FILENAME' => $components['path'], 'SCRIPT_NAME' => $components['path'], ]); } $app->instance('request', Request::create( $uri, 'GET', [], [], [], $server )); return $app; }}
首先,我们通过将 require
分配给 $app
变量来要求应用程序实例。我们没有返回它,而是使用默认 URL http://localhost
创建了一个请求实例。
当我们重新运行测试时,您应该从我们之前尝试的 dd()
调用中获得您期望的路由
phpunitPHPUnit 6.4.4 by Sebastian Bergmann and contributors. .string(23) "{"title":"Hello World"}"string(24) "http://localhost/posts/1"
现在,如果从测试用例中删除 dd()
,则使用 route()
助手的原始测试将按预期工作。
配置
如果您想使应用程序 URL 可配置,您可以更新应用程序以导入本地配置。
首先让我们创建一个 config 文件夹并复制应用程序配置
$ mkdir config/$ cp vendor/laravel/lumen-framework/config/app.php config/
接下来,打开 config/app.php
文件,并在数组中添加以下内容
'url' => env('APP_URL', 'http://localhost'),
最后,您需要通过在应用程序实例创建后将以下行添加到 bootstrap/app.php
文件中来注册配置文件
$app->configure('app');
了解更多
Lumen 的测试 API 围绕着测试 HTTP API,因此它略有不同,但很熟悉。为了使 Lumen 比 Laravel 更轻量级,做了一些差异和权衡。例如,Lumen 使用 FastRoute 包作为路由器,而不是与 Laravel 一起提供的路由器。
我觉得 Lumen 经常被误解为一个更通用的微框架,而实际上,它是一个用于制作 API 的框架。一旦您坚持这些界限,Lumen 就是构建 API 的完美选择。我建议您阅读整个手册,特别是 测试文档。