Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel 4 phpunit test: Test flagged as `risky` for not closing its own output buffers

I'm having a problem while trying to test a simple Illuminate\Http\Response object inside a phpunit test. The error in question is:

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.     

where the R is shown when running phpunit --tap as

# RISKY Test code or tested code did not (only) close its own output buffers

The class that i want to test is:

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());
    }
}

and the test is

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());
    }

}    

Note that the same error occurrs when testing any route in my app using the laravel

this->route('GET','routeName')

helper method, so this seems to be a general error related to the Response request. As far as I can think of, there is nothing within my application that is doing anything funky with the output buffering (purposefully), which is the only thing I can think of that could mess up the standard working of the Response class.

I'm using phpunit 4.3-dev, laravel 4.2.1, and mockery for the tests.

I haven't found much at all on the internet in terms of this particular risky error code, so I'm at a loss without further help.

like image 922
Inaki Avatar asked Jun 25 '14 10:06

Inaki


4 Answers

Not good enough enclosed ternary operator (?)

I had the same problem with a risky testcase while testing in Laravel 5. The problem here was, that I had a code like the following in my navigation (default layout file):

<li{{ Request::is('clients*')?' class="active"':'' }}><a href="/clients">Clients</a></li>

The test did not like this section because the the ternary operator (the ?) was not closed well enough. I replaced it with the following to get it working (added parantheses around the ternary operator section):

<li{{ (Request::is('clients*')?' class="active"':'') }}><a href="/clients">Clients</a></li>

I found this by removing the blade syntax part by part from the requested view, the layout it extended and the files that were included. At the point of removing the syntax above it worked, so there was the error.

Empty yield / section

The same error occurred, when I passed an empty value for a yield, eg like in the following scenario:

layout.blade.php

<h1>@yield('title')</h1>

page.blade.php

@extends('layout')    
@section('title','') //<-- This empty value raised the error

Other things to consider

Maybe clear but just in case you did the same mistake: You have to check all the involved files.

I had run the following test which visits the login page, enters email and password and presses the login button:

tests/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
}

So I had to check especially the following files where I made modifications:

  • app/Http/routes.php
  • app/Http/Controllers/Auth/AuthController.php -> function getLogin
  • resources/views/auth/login.blade.php (returned in Auth\AuthContoller@getLogin)
  • app/Http/Controllers/Auth/AuthController.php -> function postLogin
  • resources/views/dashboard2.blade.php (returned on successful login)
like image 188
Alexander Taubenkorb Avatar answered Nov 11 '22 16:11

Alexander Taubenkorb


Happens also in Laravel 5.
PHPUnit will throw this when response format is incorrect.

It could be due to:

  • Errors in Laravel app: check logs
  • Incorrect Blade syntax: for instance in my case, there was an excessive Blade @stop which wasn't considered as an error by Laravel (and wasn't logged)
like image 29
younes0 Avatar answered Nov 11 '22 15:11

younes0


Turns out the problem is due to the view in question using

Input::old()

inside a form. After trying to simply access Input::old('foo') inside any phpunit test, I got a

RuntimeException: Session store not set on request.

So the real culprit was in the sessions store in my unit tests instead of any Request/View render problem. Problem was solved by setting the session storage for the current Request instance inside the testRender() method:

\Illuminate\Support\Facades\Request::setSession($this->app['session.store'])

like image 40
Inaki Avatar answered Nov 11 '22 15:11

Inaki


I have same error message from PhpUnit likes yours.. I have written '@stop' on wrong line in view(blade) file.. I have edited by moving up right '@stop' to right line and than PHPUnit tests is passed!

Try to check your @section @stop block in your blade files..

like image 30
MURATSPLAT Avatar answered Nov 11 '22 15:11

MURATSPLAT