测试
介绍
Laravel 是以单元测试为基础构建的。实际上,支持使用 PHPUnit 进行测试的功能是开箱即用的,并且 phpunit.xml
文件已经为您的应用程序设置好了。除了 PHPUnit,Laravel 还利用 Symfony HttpKernel、DomCrawler 和 BrowserKit 组件来允许您在测试时检查和操作视图,从而模拟一个网络浏览器。
在 app/tests
目录中提供了一个示例测试文件。安装新 Laravel 应用程序后,只需在命令行中运行 phpunit
来运行您的测试。
定义与运行测试
要创建一个测试用例,只需在 app/tests
目录中创建一个新的测试文件。测试类应扩展 TestCase
。然后,您可以像使用 PHPUnit 一样定义测试方法。
示例测试类
class FooTest extends TestCase {
public function testSomethingIsTrue()
{
$this->assertTrue(true);
}
}
您可以通过从终端执行 phpunit
命令来运行应用程序的所有测试。
如果您定义了自己的 setUp
方法,请确保调用 parent::setUp
。
测试环境
在运行单元测试时,Laravel 会自动将配置环境设置为 testing
。此外,Laravel 在测试环境中包含 session
和 cache
的配置文件。这两个驱动在测试环境中都设置为 array
,这意味着在测试期间不会持久化会话或缓存数据。您可以根据需要创建其他测试环境配置。
从测试中调用路由
从测试中调用路由
您可以使用 call
方法轻松调用测试中的路由:
$response = $this->call('GET', 'user/profile');
$response = $this->call($method, $uri, $parameters, $files, $server, $content);
然后,您可以检查 Illuminate\Http\Response
对象:
$this->assertEquals('Hello World', $response->getContent());
从测试中调用控制器
您还可以从测试中调用控制器:
$response = $this->action('GET', 'HomeController@index');
$response = $this->action('GET', 'UserController@profile', array('user' => 1));
getContent
方法将返回响应的评估字符串内容。如果您的路由返回一个 View
,您可以使用 original
属性访问它:
$view = $response->original;
$this->assertEquals('John', $view['name']);
要调用 HTTPS 路由,您可以使用 callSecure
方法:
$response = $this->callSecure('GET', 'foo/bar');
在测试环境中,路由过滤器是禁用的。要启用它们,请在测试中添加 Route::enableFilters()
。
DOM 爬虫
您还可以调用路由并接收一个 DOM 爬虫实例,您可以使用它来检查内容:
$crawler = $this->client->request('GET', '/');
$this->assertTrue($this->client->getResponse()->isOk());
$this->assertCount(1, $crawler->filter('h1:contains("Hello World!")'));
有关如何使用爬虫的更多信息,请参阅其 官方文档。
模拟门面
在测试时,您可能经常想要模拟对 Laravel 静态门面的调用。例如,考虑以下控制器操作:
public function getIndex()
{
Event::fire('foo', array('name' => 'Dayle'));
return 'All done!';
}
我们可以通过在门面上使用 shouldReceive
方法来模拟对 Event
类的调用,这将返回一个 Mockery 模拟的实例。
模拟一个门面
public function testGetIndex()
{
Event::shouldReceive('fire')->once()->with('foo', array('name' => 'Dayle'));
$this->call('GET', '/');
}
您不应模拟 Request
门面。相反,在运行测试时将所需的输入传递给 call
方法。
框架断言
Laravel 附带了几个 assert
方法,以使测试变得更容易:
断言响应正常
public function testMethod()
{
$this->call('GET', '/');
$this->assertResponseOk();
}
断言响应状态
$this->assertResponseStatus(403);
断言响应是重定向
$this->assertRedirectedTo('foo');
$this->assertRedirectedToRoute('route.name');
$this->assertRedirectedToAction('Controller@method');
断言视图有一些数据
public function testMethod()
{
$this->call('GET', '/');
$this->assertViewHas('name');
$this->assertViewHas('age', $value);
}
断言会话有一些数据
public function testMethod()
{
$this->call('GET', '/');
$this->assertSessionHas('name');
$this->assertSessionHas('age', $value);
}
断言会话有错误
public function testMethod()
{
$this->call('GET', '/');
$this->assertSessionHasErrors();
// 断言会话有给定键的错误...
$this->assertSessionHasErrors('name');
// 断言会话有多个键的错误...
$this->assertSessionHasErrors(array('name', 'age'));
}
断言旧输入有一些数据
public function testMethod()
{
$this->call('GET', '/');
$this->assertHasOldInput();
}
辅助方法
TestCase
类包含几个辅助方法,以使测试您的应用程序更容易。
从测试中设置和清空会话
$this->session(['foo' => 'bar']);
$this->flushSession();
设置当前认证用户
您可以使用 be
方法设置当前认证用户:
$user = new User(array('name' => 'John'));
$this->be($user);
从测试中重新填充数据库
您可以使用 seed
方法从测试中重新填充数据库:
$this->seed();
$this->seed('DatabaseSeeder');
有关创建种子的更多信息,请参阅文档的 迁移和填充 部分。
刷新应用程序
正如您可能已经知道的,您可以通过 $this->app
从任何测试方法访问您的 Laravel Application
/ IoC 容器。此应用程序实例在每个测试类中都会被刷新。如果您希望手动强制应用程序在给定方法中被刷新,您可以在测试方法中使用 refreshApplication
方法。这将重置自测试用例开始运行以来在 IoC 容器中放置的任何额外绑定,例如模拟。