2016-04-07 5 views
0

У меня есть класс, который создает файл через именованный конструктор, но когда я его тестирую с помощью phpspec, он не создает файл.Создание файла в именованном конструкторе

Я не могу найти причину этого, поэтому, я думаю, свежий взгляд на мой код может помочь.

Вот мой класс файла:

<?php 

namespace Acme; 

class File 
{ 
    /** 
    * @var Path 
    */ 
    private $path; 

    /** 
    * @var FileName 
    */ 
    private $fileName; 

    private function __construct(Path $path, FileName $fileName) 
    { 
     $this->path = $path; 
     $this->fileName = $fileName; 
    } 

    public static function create(Path $path, FileName $fileName) 
    { 
     if (file_exists((string) $path . (string) $fileName)) { 
      throw new \DomainException('File already exists'); 
     } 

     if (!touch((string) $path . (string) $fileName)) { 
      throw new \DomainException('Cannot create file'); 
     } 

     return new self($path, $fileName); 
    } 
} 

Вот моя спецификация:

<?php 

namespace spec\Acme; 

use PhpSpec\ObjectBehavior; 
use Prophecy\Argument; 
use Acme\Path; 
use Acme\FileName; 

class FileSpec extends ObjectBehavior 
{ 

    private $testPath; 
    private $existingFileName = 'existingFile.extension'; 
    private $nonExistingFileName = 'nonExistingFile.extension'; 
    private $existingFilePath; 
    private $nonExistingFilePath; 

    function let() 
    { 
     $this->testPath = sys_get_temp_dir() . '/'; 
     $this->existingFilePath = $this->testPath . $this->existingFileName; 
     $this->nonExistingFilePath = $this->testPath . $this->nonExistingFileName; 

     // Creating existing file 
     if (!touch($this->existingFilePath)) { 
      throw new \Exception('Cannot create existing file for testing'); 
     } 

     // Removes non existing file 
     if (file_exists($this->nonExistingFilePath)) { 
      if (!unlink($this->nonExistingFilePath)) { 
       throw new \Exception('Cannot remove non existing file for testing'); 
      } 
     } 
    } 

    function it_does_not_create_a_file_when_the_file_already_exists(Path $path, FileName $fileName) 
    { 
     $path->__toString()->willReturn($this->testPath); 
     $fileName->__toString()->willReturn($this->existingFileName); 
     $this->beConstructedThrough('create', [$path, $fileName]); 
     $this->shouldThrow(new \DomainException('File already exists'))->duringInstantiation(); 
    } 

    function it_creates_a_new_file_if_file_does_not_exist(Path $path, FileName $fileName) 
    { 
     $path->__toString()->willReturn($this->testPath); 
     $fileName->__toString()->willReturn($this->nonExistingFileName); 
     $this->beConstructedThrough('create', [$path, $fileName]); 
     assert(file_exists($this->nonExistingFilePath)); 
    } 
} 
+0

Нет сообщений об ошибках? Проверка журналов/исключений – JazzCat

ответ

2

Это потому, что phpspec не будет экземпляр класса, пока не требуется, чтобы сделать это. Только вызовы или ожидания метода (т. Е. should*) против самого исходного класса приведут к тому, что он будет создан, а beConstructedThrough - это просто подсказка относительно , как его phpspec должен получить экземпляр.

Теперь вы можете обойти это, позвонив в какой-либо метод или, возможно, просто позвонив $this->shouldHaveType(File::class), но я бы предложил пересмотреть подход. Если вы в конечном счете интегрируете во что-то внешнее - будь то SDK, файловая система, база данных и т. Д., Вам будет намного лучше писать интеграцию . В любом случае, вы так близки к выполнению в этом случае (насмехание не должно быть действительно необходимым). phpspec больше нацелен на определение поведения/логики классов и методов. описание побочных эффектов действительно не соответствует его компетенции. Использование assert() здесь тоже намекает на это, так как это, конечно, не идиоматично для спецификаций, поддерживаемых phpspec.

Для теста интеграции PHPUnit будет лучшим выбором, так как это более общая цель. Таким образом, у вас будет гибкость при создании и утверждении по мере необходимости.