4

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

Jonathan Spooner
  • 7,682
  • 2
  • 34
  • 41
Subdigger
  • 2,166
  • 3
  • 20
  • 42
  • see http://stackoverflow.com/questions/190292/phpunit-unit-testing-with-items-that-need-to-send-headers – Manse Nov 16 '11 at 11:31

2 Answers2

3

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.

David Harkness
  • 35,992
  • 10
  • 112
  • 134
  • I know this is kind of old, but where do you need to write this? I have the same exact problem, but I don't understand from your answer where should I write these lines, I tried in the main bootstrap also in the ControllerTestCase but with no luck – Uffo Jan 16 '13 at 20:29
  • Are you using `Zend_Test_PHPUnit_ControllerTestCase`? It injects the `Zend_Controller_Response_HttpTestCase` response into the front controller in `bootstrap()`. – David Harkness Jan 16 '13 at 22:23
  • I still don't see an answer to Uffo's question (which I have as well). Which file does the setResp function go into? I tried adding the code to Zend_Test_PHPUnit_ControllerTestCase, but it didn't work. – blainarmstrong Feb 17 '13 at 05:57
  • @blainarmstrong - Looking at the ZF source (1.12.1, 1.11.10, and 1.11.0) I cannot find `_getResp()`. In our testing framework I do the above in our PHPUnit bootstrap. However, you should be able to inject your own `Zend_Controller_Front` subclass that overrides `getResponse()` to return a new `Zend_Controller_Response_HttpTestCase`. – David Harkness Feb 17 '13 at 20:17
  • It worked for me! Thank you, but anyone can explain why PHPUnit will generate the output before the test runs? – MengT Oct 13 '14 at 10:51
  • @Truman'sworld PHPUnit outputs the version, author, and configuration file location before running any tests along with the individual test status and percentage complete while it runs them. It does this so you can see results immediately. – David Harkness Oct 13 '14 at 20:19
0

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.

Community
  • 1
  • 1
Saul Martínez
  • 920
  • 13
  • 28