Laravel 4 phpunit 测试:测试标记为“风险”,因为没有关闭自己的输出缓冲区
Posted
技术标签:
【中文标题】Laravel 4 phpunit 测试:测试标记为“风险”,因为没有关闭自己的输出缓冲区【英文标题】:Laravel 4 phpunit test: Test flagged as `risky` for not closing its own output buffers 【发布时间】:2014-08-15 20:12:55 【问题描述】:我在尝试在 phpunit 测试中测试简单的 Illuminate\Http\Response 对象时遇到问题。有问题的错误是:
PHPUnit 4.3-dev by Sebastian Bergmann.
Configuration read from /var/MyApp/phpunit.xml
....................R.................
Time: 2.71 seconds, Memory: 76.75Mb
OK, but incomplete, skipped, or risky tests!
Tests: 38, Assertions: 55, Risky: 1.
phpunit --tap
as 运行时显示 R 的位置
# RISKY Test code or tested code did not (only) close its own output buffers
我要测试的类是:
class PrettyError
/**
* Renders a pretty 500 error page view
*
* @return string with error view
*/
public function render()
return Response::make(View::make('viewName')->with('param','value')->render(), 500, array());
测试是
class Pretty500Test extends BaseTest
/** @var Pretty500 */
private $pretty500;
/**
* Set dependencies
*/
public function __construct()
$this->pretty500 = app(PrettyError::class);
public function testRender()
$response = $this->pretty500->render();
//assertions below, never get reached cause tests aborts after above call
$this->assertsTrue('500',$response->getStatus());
请注意,使用 laravel 在我的应用程序中测试任何路线时都会发生相同的错误
this->route('GET','routeName')
helper 方法,所以这似乎是与响应请求相关的一般错误。据我所知,我的应用程序中没有任何东西在输出缓冲(有目的地)做任何时髦的事情,这是我能想到的唯一可能会破坏 Response 类的标准工作的事情。
我正在使用 phpunit 4.3-dev、laravel 4.2.1 和 mocky 进行测试。
就这个特别危险的错误代码而言,我在互联网上根本没有找到太多信息,所以如果没有进一步的帮助,我会不知所措。
【问题讨论】:
在全新安装的 Laravel 上尝试一下 - 你仍然遇到问题吗? 不,我还没有尝试过全新安装,接下来我会这样做,以确保它不在我正在使用的 TestCase 设置中 更新:我将问题隔离了一点,它与 Request 类本身无关,而是与内部 View 调用有关,所以基本上View::make('viewName')->with('param','value')->render()
触发了 phpunit 风险警告,没有任何其他内容测试。由于我的应用程序中的 View
实例不是本机 laravel 实例,而是使用自定义实例进行热交换,但建立在此之上(它注册了一些有用的 View 作曲家),也许其中有一些测试不喜欢的东西
实际上 - 我刚刚注意到您正在“制作”一个视图,渲染它,然后将其发送到 Response 类以重新渲染?
是的,基本上我正在创建一个带有自定义标题和状态代码的响应,它的内容只是呈现的视图。我现在看了一下文档,有一个速记方法Response::view('hello')->header('Content-Type', $type);
可以立即使用它,但除此之外它是正确的 AFAIK
【参考方案1】:
原来问题是由于使用了有问题的视图
Input::old()
在表单中。在尝试在任何 phpunit 测试中简单地访问 Input::old('foo')
后,我得到了一个
RuntimeException: Session store not set on request.
所以真正的罪魁祸首是在我的单元测试中的会话存储中,而不是任何请求/视图渲染问题。通过在 testRender() 方法中为当前 Request 实例设置会话存储解决了问题:
\Illuminate\Support\Facades\Request::setSession($this->app['session.store'])
【讨论】:
【参考方案2】:我遇到了非常相似的问题。问题是我试图在视图中获取非对象(NULL)的属性,而不是 PHP 错误“试图获取非对象的属性”phpunit 显示“好的,但不完整、跳过或有风险的测试!” .
因此,如果您遇到同样的问题,请检查视图文件中的此类错误。
【讨论】:
【参考方案3】:也发生在 Laravel 5 中。 当响应格式不正确时,PHPUnit 会抛出这个。
这可能是由于:
Laravel 应用中的错误:检查日志 不正确的 Blade 语法:例如在我的例子中,有一个过多的 Blade@stop
被 Laravel 不认为是错误(并且没有被记录)
【讨论】:
与我的安装相同。没有 @endsection 来关闭我的模板文件中打开的部分。 也只是想插话。我在为 Laravel 5.1app 编写测试时遇到了这个令人发狂的风险问题。这条评论让我走上了正确的道路,事实证明我在 Blade 模板中有一个过时的@show
语句,这导致了问题。如果您想在您的 Laravel 应用程序(或与此相关的任何应用程序)中查找至少包含一个 @endsection
语句的所有文件,请运行以下命令: grep -cr "@endsection" 。 | sed '/:0$/d' | sort -k2n -t:这很有用,因为 grep 的默认行为是列出 所有 个文件和出现次数。【参考方案4】:
我有来自 PhpUnit 的相同错误消息,喜欢你的。我在视图(刀片)文件的错误行上写了 '@stop'。我通过将右 '@stop' 移动到右行进行了编辑,而不是 PHPUnit 测试通过了!
尝试检查刀片文件中的 @section @stop 块。
【讨论】:
【参考方案5】:封闭式三元运算符 (?) 不够好
在 Laravel 5 中进行测试时,我遇到了同样的风险测试用例问题。这里的问题是,我的导航(默认布局文件)中有如下代码:
<li Request::is('clients*')?' class="active"':'' ><a href="/clients">Clients</a></li>
测试不喜欢这部分,因为三元运算符(?
)关闭得不够好。我将其替换为以下内容以使其正常工作(在三元运算符部分周围添加了括号):
<li (Request::is('clients*')?' class="active"':'') ><a href="/clients">Clients</a></li>
我通过从请求的视图、它扩展的布局和包含的文件中逐部分删除刀片语法找到了这一点。在删除上面的语法时它起作用了,所以出现了错误。
空产量/节
当我为收益传递一个空值时,发生了同样的错误,例如在以下场景中:
layout.blade.php
<h1>@yield('title')</h1>
page.blade.php
@extends('layout')
@section('title','') //<-- This empty value raised the error
其他需要考虑的事项
也许很清楚,但以防万一您犯了同样的错误:您必须检查所有涉及的文件。
我运行了以下测试,访问登录页面,输入电子邮件和密码并按下登录按钮:
测试/AuthenticationTest.php
<?php
class AuthenticationTest extends TestCase
// [...]
public function testLoginSuccessful()
$password = str_random();
$user = factory(App\User::class)->create(['password' => $password]);
$this->visit(route('login'))
->type($user->email, 'email')
->type($password, 'password')
->press('Login')
->seePageIs(route('dashboard2'));
app/Http/routes.php
<?php
Route::get('auth/login', 'Auth\AuthController@getLogin')->name('login');
Route::post('auth/login', 'Auth\AuthController@postLogin');
app/Http/Controllers/Auth/AuthController.php
<?php
// [...]
class AuthController extends Controller
// [...]
protected $redirectPath = '/dashboard2'; // <-- check this file as well
所以我必须特别检查以下我进行修改的文件:
app/Http/routes.php app/Http/Controllers/Auth/AuthController.php -> 函数getLogin resources/views/auth/login.blade.php(在 Auth\AuthContoller@getLogin 中返回) app/Http/Controllers/Auth/AuthController.php -> 函数postLogin resources/views/dashboard2.blade.php(登录成功后返回)【讨论】:
空白部分也引起了我的注意。将其更改为 @section('name', null) 使其没有风险,但现在看起来像代码异味:-/ 啊@section('title','')
引起了问题。谢谢!
对我来说,我必须将 @section('title')
包装在 @hasSection
块中 - 使用 null
而不是 ''
并没有成功。【参考方案6】:
重复的@section('content')
行有同样的问题
@section('content')
@section('content')
...
@endsection
错字!!
【讨论】:
以上是关于Laravel 4 phpunit 测试:测试标记为“风险”,因为没有关闭自己的输出缓冲区的主要内容,如果未能解决你的问题,请参考以下文章
在 laravel 4 中使用 phpunit 测试 POST
Laravel 4 PHPUnit Sqlite 数据库,每次测试前删除项目
如何使用 phpunit 在 Laravel 4 中测试命名空间对象