Я подготовил простой функциональный тест для проверки состояния контроллера, который возвращает документ Excel в ответ:
<?php
namespace App\Tests\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class CustomersControllerTest extends WebTestCase
{
private $client = null;
public function setUp()
{
$this->client = static::createClient([], [
'PHP_AUTH_USER' => USERNAME,
'PHP_AUTH_PW' => PASSWORD
]);
}
public function testActivityEXCEL()
{
$this->client->request('GET', '/customers/activity-excel');
$this->assertEquals(200, $this->client->getResponse()->getStatusCode());
}
}
Контроллер возвращает документ Excel, созданный https://phpspreadsheet.readthedocs.io/en/latest/:
/**
* @Route("/activity-excel", name="customers_activity_excel")
* @Security("is_granted('ROLE_RFM_CUSTOMERS_ACTIVE_INACTIVE')")
*
* @param TranslatorInterface $translator
* @param ChartManager $chartManager
*
* @return JsonResponse
*/
public function activityEXCEL(TranslatorInterface $translator, ChartManager $chartManager)
{
$filters = array();
foreach($this->get('session')->all() as $key => $value){
if (strpos($key, 'customers_activity_') !== false) {
$filters[str_replace('customers_activity_', '', $key)] = $value;
}
}
$data = $chartManager->activityChart($filters);
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->setCellValue('A1', $translator->trans('general.information'))->getStyle('A1')->getFont()->setBold(true);
$sheet->setCellValue('A2', $translator->trans('view'));
$sheet->setCellValue('A3', $translator->trans('chart.type'));
$sheet->setCellValue('A4', $translator->trans('from'));
$sheet->setCellValue('A5', $translator->trans('to'));
$sheet->setCellValue('A6', $translator->trans('chart.active'));
$sheet->setCellValue('A7', $translator->trans('chart.inactive'));
$sheet->setCellValue('B2', $data['table']['view'] == 1 ? $translator->trans('for.months') : $translator->trans('everybody'));
$sheet->setCellValue('B3', $translator->trans($data['table']['type']));
$sheet->setCellValue('B4', $data['table']['date_from']);
$sheet->setCellValue('B5', $data['table']['date_to']);
$sheet->setCellValue('B6', $data['table']['active']);
$sheet->setCellValue('B7', $data['table']['inactive']);
if($data['table']['monthly']){
$sheet->setCellValue('A9', $translator->trans('table.month'))->getStyle('A9')->getFont()->setBold(true);
$sheet->setCellValue('B9', $translator->trans('active'))->getStyle('B9')->getFont()->setBold(true);
$sheet->setCellValue('C9', $translator->trans('inactive'))->getStyle('C9')->getFont()->setBold(true);
$i = 10;
foreach($data['table']['dataset'] as $item){
$sheet->setCellValue('A'.$i, $item['label']);
$sheet->setCellValue('B'.$i, $item['data'][0]);
$sheet->setCellValue('C'.$i, $item['data'][1]);
$i++;
}
}
$img = $chartManager->preparePng($filters['img']);
$drawing = new \PhpOffice\PhpSpreadsheet\Worksheet\Drawing();
$drawing->setName('Chart');
$drawing->setDescription('Chart');
$drawing->setPath($img['path']);
$drawing->setWidth($img['width']*0.6);
$drawing->setHeight($img['height']*0.6);
$drawing->setCoordinates('G2');
$drawing->setWorksheet($spreadsheet->getActiveSheet());
$writer = new Xlsx($spreadsheet);
$response = new StreamedResponse(
function () use ($writer) {
$writer->save('php://output');
}
);
$response->headers->set('Content-Type', 'application/vnd.ms-excel');
$response->headers->set('Content-Disposition', 'attachment; filename="Report_'.date("m_d_Y").'.xlsx"');
$response->headers->set('Cache-Control','max-age=0');
return $response;
}
Тест выполнен правильно, однако двоичное значение файла отображается в консоли.
Как исправить эту ошибку или как правильно протестировать аналогичные контроллеры?
EDIT
Спасибо за @Jakumi Я нашел решение. Виновен StreamedResponse php: // вывод. Теперь мой тест выглядит так:
/**
* @dataProvider provideFilters
*/
public function testActivityEXCEL($filters)
{
$session = $this->client->getContainer()->get('session');
foreach($filters as $key => $value){
$session->set($key, $value);
}
ob_start();
$this->client->request('GET', '/customers/activity-excel');
$response = ob_get_clean();
$this->assertEquals(200, $this->client->getResponse()->getStatusCode());
$this->assertSame(true, !ctype_print($response));
}
Надеюсь, это кому-нибудь поможет