Search code examples
phpjsonzend-framework2phpunitajax-request

Test if method is called from and AJAX request or from PhpUnit


I've started implementing unit tests on my current project.

While all unit test currently pass, due to convenience, I made a change to the jsonResponse method to also send json headers. This helps me see the json response as a tree in the Chrome console.

Now the unit tests are failing due to

Cannot modify header information - headers already sent by
(output started at [fullPath]/phpunit/src/Util/Printer.php:134)

Digging deeper, I found that this can be fixed by adding @runInSeparateProcess in the docBlocks.

But this just leads to:

PHP Fatal error: Class 'PHPUnit_Util_Configuration' not found in - on line 365
PHP Stack trace:
PHP 1. {main}() -:0

This is one of my json methods (this is called at the end of several methods which are called through AJAX requests):

/**
 * Helper function to print a json encoded success message back to the frontend.
 *
 * @param array $returnData
 *
 * @return bool
 *
 * @runInSeparateProcess
 */
public function returnJsonSuccess($returnData = [])
{
    header('Content-Type: application/json');
    echo json_encode(
        [
            "success" => true,
            "data"    => $returnData,
        ]
    );
    return true;
}

So, cutting to the chase, how can i make this work properly?

One of my options is to detect if the method is called from a unit test and conditionally send the headers only if it's called normally. I'm thinking easiest way is to define an environment variable or a constant in the bootstrap file and check for that in my BaseController.

Is there a cleaner way of getting my unit tests to work again while also keeping the json headers sent?


Solution

  • Solved it myself with:

    /**
     * Helper function to print a json encoded success message back to extJs.
     *
     * @param array $returnData
     *
     * @return bool
     */
    public function returnJsonSuccess($returnData = [])
    {
        $request = $this->getRequest();
        if ($request && $request->isXmlHttpRequest()) {
            header('Content-Type: application/json');
        }
        echo json_encode(
            [
                "success" => true,
                "data"    => $returnData,
            ]
        );
        return true;
    }
    

    ZendFramework, using the Request class, can detect if the call is made from an AJAX request or not. This way, I only send the headers if there's an AJAX request.