I have a function that creates CSV data and lets the user download it in the browser, basically like this:
function f() {
if ($fp = fopen('php://output', 'w')) {
header("Content-Type: text/csv");
header("Content-Disposition: attachment; filename=\"foo.csv\"");
fputcsv($fp, $someArrayGoesHere);
flush();
fclose($fp);
// debugging, explained below
error_log(print_r(xdebug_get_headers(), true));
}
}
The code works, presenting the user with a download dialog.
Now, I'm trying to write a PHPunit test to confirm that the two HTTP headers get set. Realizing that headers_list() doesn't work in CLI context (php_sapi_name() == 'cli'), I'm using xdebug_get_headers() to retrieve the headers for testing.
Now comes the trouble. The debugging line in my code above, when run on the web, always prints the headers I expect:
Array
(
[0] => X-Content-Type-Options: nosniff
[1] => Content-Type: text/csv
[2] => Content-Disposition: attachment; filename="foo.csv"
)
But when I run this code in phpunit, the PHPUnit_Util_Printer::write function appears to be producing output before my code sets the headers, and prevents them from being set, producing this debug output:
Cannot modify header information - headers already sent by (output started
at /usr/share/pear/PHPUnit/Util/Printer.php:172)
Array
(
[0] => Content-type: text/html
)
This earlier write is not being produced by me, so is there a way around it? How do I test for my CSV-related headers using phpunit?
I've already read the advice given in these questions, but it hasn't helped:
- Headers already sent by PHP
- PHPUnit - test for expected headers
- PHPUnit - Unit Testing with items that need to send headers
- Test PHP headers with PHPunit
- Setting HTTP headers to be able to run test cases
I also tried using @runInSeparateProcess with the unit test, but the test crashes horribly: ".Unexpected non-MediaWiki exception encountered, of type "Exception", exception 'Exception' with message 'Serialization of 'Closure' is not allowed' in /usr/share/pear/PHPUnit/Util/GlobalState.php:354". (This is a MediaWiki unit test for a custom extension.)