2016-02-09 2 views
1

В один проект, который я нашел такие строки кода:PHPUnit испытаний для цепи Еореп/FWRITE

protected function save($content, $path) 
{ 
    // ... 
    if (($handler = @fopen($path, 'w')) === false) { 
     throw new Exception('...'); 
    } 

    // ... 
    if (@fwrite($handler, $content) === false) { 
     throw new Exception('...'); 
    } 

    // ... 
    @fclose($handler); 
} 

Я хотел бы проверить этот метод с PHPUnit, но я немного застрял с правильной Test- дело. Если я переведу неправильный $path или правильный $path с неправильными разрешениями (например, 0444), то все будет остановлено при первом исключении. Если я правильно передаю $path с правильными разрешениями, то PHP также сможет записать в файл, а второе исключение не будет достигнуто.

Итак, есть ли способ проверить второе исключение без перезаписи этого метода?

Или лучше проверить как fopen, так и fwrite в одном состоянии и использовать только одно исключение для обоих?

Или лучший вариант состоит в том, чтобы разделить этот метод на два - один для открытия и один для записи - и проверить их отдельно?

+4

Я хотел бы использовать высмеивал $ путь, см. https://phpunit.de/manual/current/en/test-doubles.html#test-doubles.mocking-the-filesystem - с помощью vfsStream вы можете установить квоту виртуального диска, которая должна (несмотря на сбои hw) - самая распространенная причина, по которой fwrite возвращает false. vfsStream :: setQuota() - метод выбора. –

+0

@ l-x ваш комментарий должен быть ответом :) –

+0

Да, и я мог определенно принять его :) Хороший пакет для тестирования. –

ответ

2

Лучший способ достичь вашей цели - использовать издеваемую файловую систему. Я рекомендую использовать vfsStream:

$ composer require mikey179/vfsStream 

Прежде всего я должен отметить, что Fread возвращает только ложные если вы вызываете эту функцию с недопустимым аргументом. Если возникнет какая-либо другая ошибка, она вернет количество записанных байтов. Таким образом, вам придется добавить еще одну проверку:

class SomeClass { 
    public function save($content, $path) 
    { 
     // ... 
     if (($handler = @fopen($path, 'w')) === false) { 
      throw new Exception('...'); 
     } 

     $result = @fwrite($handler, $content); 

     // ... 
     if ($result === false) { // this will only happen when passing invalid arguments to fwrite 
      throw new Exception('...'); 
     } 

     // ... 
     if ($result < strlen($content)) { // additional check if all bytes could have been written to disk 
      throw new Exception('...'); 
     } 

     // ... 
     @fclose($handler); 
    } 
} 

В TestCase для метода может выглядеть следующим образом:

class SomeClassTest extends \PHPUnit_Framework_TestCase { 

    /** 
    * @var vfsStreamDirectory 
    */ 
    private $fs_mock; 

    /** 
    * @var vfsStreamFile 
    */ 
    private $file_mock; 

    /** 
    * @var $sut System under test 
    */ 
    private $sut; 

    public function setUp() { 
     $this->fs_mock = vfsStream::setup(); 
     $this->file_mock = new vfsStreamFile('filename.ext'); 
     $this->fs_mock->addChild($this->file_mock); 

     $this->sut = new SomeClass(); 
    } 

    public function testSaveThrowsExceptionOnMissingWritePermissionOnFile() { 
     $this->expectException(\Exception::class); 

     $this->file_mock->chmod(0); 
     $this->sut->save(
      'content', 
      $this->file_mock->url() 
     ); 
    } 

    public function testSaveThrowsExceptionOnMissingWritePermissionOnDirectory() { 
     $this->expectException(\Exception::class); 

     $this->fs_mock->chmod(0); 
     $this->sut->save(
      'content', 
      $this->fs_mock->url().'/new_file.ext' 
     ); 
    } 

    public function testSaveThrowsExceptionOnInvalidContentType() { 
     $this->expectException(\Exception::class); 

     $this->fs_mock->chmod(0); 
     $this->sut->save(
      $this, 
      $this->file_mock->url() 
     ); 
    } 

    public function testSaveThrowsExceptionOnDiskFull() { 
     $this->expectException(\Exception::class); 

     $this->fs_mock->chmod(0777); // to be sure 
     $this->file_mock->chmod(0777); // to be sure 

     vfsStream::setQuota(1); // set disk quota to 1 byte 

     $this->sut->save(
      'content', 
      $this->file_mock->url() 
     ); 
    } 
} 

Я надеюсь, что я мог бы помочь ...

Смежные вопросы