如何使用PHPUnit断言路由输出CSV

时间:2015-04-23 18:43:22

标签: csv phpunit

我对测试很陌生,而且我已经接受了一项我不知道如何写作的测试。我的应用程序中有一条路线,它所做的只是从一些在线数据生成一个CSV文件。我需要测试以查看是否创建了该CSV文件。我怎么做。这是我的路线:

...generate data...

$strContent = "'Title', 'MediaId', 'Original File Name'". "'\n";
foreach ($objData->media_list as $objMedia) {
    $strContent .= "'" . $objMedia->title . "', '" . $objMedia->media_id . "', '" . $objMedia->original_filename . "'\n";
}

    /**
     * Comment this line out to output file
     */
    // exit;

    header('Pragma: public');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Content-Type: application/force-download');
    header('Content-Type: application/csv');
    header('Content-Type: application/download');
    header('Content-Disposition: attachment;filename=Limelight.csv');

    echo $strContent;
    exit;

这是我的测试:

public function testIndex()
{
    $this->call('GET', '/limelight');
    $this->assertFileExists('Limelight.csv');
}

测试失败,但我甚至不确定它是否是正确的测试。该文件未保存到文件系统。它直接输出到浏览器。我如何在PHPUnit中测试它?

3 个答案:

答案 0 :(得分:1)

也许更简单的事情:

public function testCsv(){
    $response = $this->call('GET', $urlToControllerThatGeneratesCsvDownload);
    $this->assertTrue(strpos($response->content(), 'csv') !== false);
}

在Controller中,csv的创建方式如下:

return \Excel::create('XXXXX', function($excel) {
    $excel->sheet('Sheet 1', function($sheet) {
        .....
    });
})->download('csv');

这对我有用

答案 1 :(得分:0)

如何使用file_get_contents()获取文件并将其转储到变量中,然后可以测量其大小,内容等:

$data = file_get_contents($url);
$this->assertTrue(strlen($data) > $someThreshold);
$this->assertTrue(preg_match('/someString/', $data));
$this->assertEquals($knownHash, md5($data));

或者,如果您想要非常彻底,可以扫描每一行以确保它是有效的CSV并包含您的期望:

$fp = fopen($url, 'r');
while (true) {
    $line = fgetcsv($fp);
    if (feof($fp)) {
        break;
    }
    $this->assertTrue(is_array($line));
    $this->assertTrue(count($line) === $expectedNumberOfItems);
    // etc...
}

答案 2 :(得分:0)

代码中unit test至少有两件事:

  1. 已正确生成CSV
  2. 脚本实际发送CSV
  3. 对于#1,问题是$strContent是一个局部变量,并且没有公开。验证它的一种方法是将CSV生成代码提取到另一个方法中,并对该方法进行单元测试。

    对于#2,你需要一些帮助方法/类,在代码和本机PHP代码之间使用它作为bridge。例如:

    class MyHttpResponse {
        public function header($header, $replace=false, $httpCode=200) {
            header($location, $replace, $httpCode);
        }
    
        public function sendBody($body) {
            echo $body;
        }
    }
    

    并从那里获取原始代码调用方法,而不是PHP本机代码。然后,您可以使用mocksfakes来断言发送了正确的headersbody。断言body响应也涵盖#1的测试,因此如果在body上执行正确的断言,则可以跳过这些测试。

    在编写计划对其进行单元测试的代码时,您要记住的一件事是,您应该尽可能多地将工作委托给其他方法/类。这不仅仅是为了unit testing带来的好处,它还会带您进入Single Responsibility Principle。就SRP而言,您的index方法有点不知所措,并且不应该负责从数据数组生成字符串,这应该是数据处理器类/方法的角色。