14

I have this strange problem when i call the parent::setUp() on my TestCase class for unit test a class when i run phpunit it throw me this error:

1) MatchRequestRepositoryTest::test_find_requests_by_match_id ErrorException: session_start(): Cannot send session cookie - headers already sent by (output started at /var/www/project.dev/vendor/phpunit/phpunit/PHPUnit/TextUI/TestRunner.php:459)

What can be the problem? Thanks for any help.

3
  • 2
    Please check this : stackoverflow.com/questions/8028957/… Commented Apr 24, 2014 at 13:40
  • You'll have to share the contents of your test. Also, is your application doing any direct manipulation of sessions, either via native session_ function calls or Session::? Commented Apr 25, 2014 at 11:25
  • Possible duplicate of Test PHP headers with PHPunit Commented Jun 27, 2016 at 3:20

4 Answers 4

33

One way to handle this in PHPUnit is to send output to stderr instead of stdout as is demonstrated by this answer.

phpunit --stderr

Or by adding stderr="true" in your phpunit.xml as is pointed out in this comment.

Sign up to request clarification or add additional context in comments.

5 Comments

is there any backfire using this? or no problem at all? thanks
@Carlos I still haven't found any problem with it.
This should be the best answer!
I know this is an old thread, but the problem i have on this solution is that it does not generate a junit.xml file from phpunit.xml for my unit test. I guess it is because it outputs to stderr instead of stdout.
@xCHAN that's an interesting caveat! I'd never thought about that side effect. You should post a solution if you discover a better option and ping me when you do.
27

(UPDATE: Thanks to comment by Louis Charette, this will only work in php 7.1 and earlier (and reading the bug report, it sounds like a regression they don't intend to fix. The better solution is therefore Jeff Puckett's (https://stackoverflow.com/a/38045422/841830), of giving the --stderr flag on the commandline to phpunit. This keeps stdout for your code, stderr for phpunit, and so they don't clash.)


The problem is that you have some code, perhaps deep in the framework you use, that calls session_start(). That, in turn, wants to send a cookie. But PHPUnit has already started writing output to stdout.

The point to understand here is that this is just a unit test, no-one cares about the header. So just suppress the error message. And the way you do that, without altering the system-under-test, is to call session_start() in your own unit test (either before parent::setUp() or inside that setUp function). And use the @ prefix to suppress errors. e.g.

function setUp() {
  @session_start();
  parent::setUp();
  ...
}

5 Comments

Unfortunately, this solution will still produce an error for your test. It will produce something like this: There was 1 error: 1) Classname::ClassTest A session had already been started - ignoring session_start()
@w00tland The @ should stop any errors or warnings being reported. Do you have the @ on the line it is complaining about? And does adding/removing the @ change the error message? (If you cannot get the message to go away, it might be worth starting a new question; this one was about how to get rid of the "headers already sent" complaint.)
I know it should prevent warnings from being reported. The message I shared above is the result of suppressing the message. And yes, I get the Cannot send session cookie - headers already sent by message if I remove the @. And I have the exact same problem; I'm just trying to get rid of the "headers already sent" message.
For people finding this though Google, this fix might produce another set of errors with PHP 7.2 in relation with session_set_save_handler. See : bugs.php.net/bug.php?id=75628 Jeff Puckett answer is a better solution in relation to PHP 7.2 change.
@LouisCharette Thanks. I've updated the answer with that info.
4
 /**
 * @test
 * @runInSeparateProcess
 */
public function testName(){
    //... your test
}

2 Comments

Please add a comment, explaining your answer.
@baikho this code is pretty much selfexplaining. It lets the test run in a seperate process so the headers are not already sent by phpunit.
1

In Laravel I avoided the issue by checking the environment and avoiding problematic code for 'testing' environment.

// Code working in Laravel 4.2
if(App::environment() != 'testing') {
        // this will be skipped when testing
        setcookie('key', $val, time() + (86400 * 999), '/');
}

NOTE - Warning: this means you cannot test this piece of code!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.