Subdigger
Subdigger

Reputation: 2203

Zend_Controller_Response_Exception: Cannot send headers;

when runing all test for zend application, this line:

protected function _getResp()
{
    if (is_null($this->_response))
        $this->_response = new Zend_Controller_Response_Http();
    return $this->_response;
}
.......
$this->_getResp()->setHeader('Content-Type', 'text/html; charset=utf-8', true);

generates following error:

Zend_Controller_Response_Exception: Cannot send headers; headers already sent in /usr/share/php5/PEAR/PHPUnit/Util/Printer.php, line 173

and as a result - test fails

Upvotes: 4

Views: 1904

Answers (2)

Saul Martínez
Saul Martínez

Reputation: 920

In my case I have custom request and response objects: My_Controller_Request_Rest and My_Controller_Response_Rest.

What I did to solve this, I created a new My_Controller_Request_RestTestCase and My_Controller_Response_RestTestCase, which extend Zend_Controller_Request_HttpTestCase and Zend_Controller_Response_HttpTestCase respectively.

What David Harkness suggested actually solves the problem. The only thing is that your objects must extend the HttpTestCase class corresponding to each class.

You need to create the setters for each object as you are not allowed to set them directly.

I have the following ControllerTestCase code:

tests/application/controllers/ControllerTestCase.php

abstract class ControllerTestCase extends Zend_Test_PHPUnit_ControllerTestCase
{
    /**
     * Application instance.
     * @var Zend_Application
     */
    protected $application;

    /**
     * Setup test suite.
     *
     * @return void
     */
    public function setUp()
    {
        $this->_setupInitializers();
        $this->bootstrap = array(
            $this,
            'applicationBootstrap',
        );
        parent::setUp();

        $this->setRequest(new My_Controller_Request_RestTestCase());
        $this->setResponse(new My_Controller_Response_RestTestCase());
    }
}

My custom request and response objects have the following signature:

library/My/Controller/Request/Rest.php

class My_Controller_Request_Rest extends Zend_Controller_Request_Http
{
    // Nothing fancy.
}

library/My/Controller/Response/Rest.php

class Bonzai_Controller_Response_Rest extends Zend_Controller_Response_Http
{
    // Nothing fancy either
}

Now, this is what I couldn't figure out, how to avoid repeating the same code in library/My/Controller/Request/Rest.php and library/My/Controller/Controller/Request/RestTestCase.php. The code is the same in my case in Request/Rest.php and Request/RestTestCase.php as well as in Response/Rest.php and Response/RestTestCase.php, but they extend Zend_Controller_(Request|Response)_HttpTestCase.

I hope I made myself clear. I know the post is old, but I think it's worth to extend this a little bit more.

Upvotes: 0

David Harkness
David Harkness

Reputation: 36562

This is caused because PHPUnit generates output before your test even runs. You need to inject a Zend_Controller_Response_HttpTestCase in your test case. This subclass of Zend_Controller_Response_Http doesn't actually send headers or output anything, and it won't throw an exception because it doesn't care that output has already been sent.

Simply add the following method to the above class.

public function setResp(Zend_Controller_Response_Http $resp) {
    $this->_response = $resp;
}

Create a new Zend_Controller_Response_HttpTestCase and pass it to setResp() on the object you're testing. This will also allow you to validate that the correct headers were "sent" along with the output.

Upvotes: 3

Related Questions