PHPUnit:我如何模拟这个文件创建?

时间:2017-06-27 07:45:50

标签: php symfony unit-testing phpunit vfs-stream

我想使用vfsstream

模拟文件的创建
class MyClass{

  public function createFile($dirPath)
  {
    $name = time() . "-RT";
    $file = $dirPath . '/' . $name . '.tmp';

    fopen($file, "w+");
    if (file_exists($file)) {
        return $name . '.tmp';
    } else {
        return '';
    }
  }
}

但是当我尝试测试文件创建时:

$filename = $myClass->createFile(vfsStream::url('/var/www/app/web/exported/folder'));

我收到错误:

  

无法打开流:“org \ bovigo \ vfs \ vfsStreamWrapper :: stream_open”   呼叫失败fopen(vfs:// var / www / app / web / exported / folder)

我看到this question正在讨论模拟文件系统,但它没有关于文件创建的信息。 vfsstream是否支持使用fopen函数创建文件? 如何测试文件创建?

2 个答案:

答案 0 :(得分:2)

尝试使用vsf流设置创建,例如:

$root = vfsStream::setup('root');
$filename = $myClass->createFile($root->url());

希望这个帮助

作为工作示例:

/**
 * @test
 * @group unit
 */
public function itShouldBeTested()
{
    $myClass = new MyClass();

    $root = vfsStream::setup('root');
    $filename = $myClass->createFile($root->url());
    $this->assertNotNull($filename);
    var_dump($filename);
}

这将产生

  

(dev)bash-4.4 $ phpunit -c app --filter = itShouldBeTested PHPUnit   4.8.26由Sebastian Bergmann和贡献者。

     

.string(17)" 1498555092-RT.tmp"

     

时间:13.11秒,内存:200.00MB

     

好(1次测试,1次断言)

答案 1 :(得分:0)

OOP方式如下:     

interface FileClientInterface {
    function open($path);
    function exist($path);
}

class FileClient implements FileClientInterface {
    function open($path)
    {
        fopen($path, "w+");
    }

    function exist($path)
    {
        return file_exists($path);
    }
}

class MyClass
{
    private $fileClient;

    /**
     * MyClass constructor.
     * @param $fileClient
     */
    public function __construct(FileClientInterface $fileClient)
    {
        $this->fileClient = $fileClient;
    }

    public function createFile($dirPath)
    {
        $name = time() . "-RT";
        $file = $dirPath . '/' . $name . '.tmp';

        $this->fileClient->open($file);
        fopen($file, "w+");
        if ($this->fileClient->exist($file)) {
            return $name . '.tmp';
        } else {
            return '';
        }

    }
}

class MockFileClient implements FileClientInterface {
    public $calledOpen = 0;
    public $calledExists = 0;

    public function open($path)
    {
        $this->calledOpen ++;
    }

    public function exist($path)
    {
        $this->calledExists++;
    }

}


//not the test
$mockFileClient = new MockFileClient();
$myClass = new MyClass($mockFileClient);
$myClass->createFile('/test/path');

print_r($mockFileClient->calledOpen . PHP_EOL);
print_r($mockFileClient->calledExists . PHP_EOL);

所以我们创建了一个接口(FileClientInterface)和两个实现类,一个用于生产一个用于测试(一个用于模拟)。测试实现只是在调用方法时递增计数器。这样我们就可以在测试中解耦实际的I / O方法。