我有一个通过命名构造函数创建文件的类,但当我使用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 specAcme;
use PhpSpecObjectBehavior;
use ProphecyArgument;
use AcmePath;
use AcmeFileName;
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));
}
}
这是因为phpspec在被要求之前不会实例化类。只有对原始类本身的方法调用或期望(即should*
)才会导致它被实例化,而beConstructedThrough
只是一个提示,提示phpspec应该如何获得实例。
现在,您可以通过调用某种方法来解决这个问题,甚至可以只调用$this->shouldHaveType(File::class)
,但我建议重新思考这种方法。如果您最终将集成到外部的东西中——无论是SDK、文件系统、数据库等,那么编写集成测试会更好。无论如何,在这种情况下,你已经非常接近了(嘲笑应该没有必要)。phpspec更倾向于指定类和方法的行为/逻辑。。描述副作用并不完全符合它的职权范围。这里使用assert()
也是一个提示,因为这对于phpspec支持的规范来说肯定不是惯用的。
对于集成测试,PHPUnit将是一个更好的选择,因为它更通用。。因此,您可以根据需要灵活地实例化和断言。