2012-08-23 13 views
11

次のシナリオ(これは、生産コードではありません)考えてみますので、何が問題だ、PHPUnit:このファイルシステムをどうやって模擬しますか?

class MyClass { 
    public function myMethod() { 
     // create a directory 
     $path = sys_get_temp_dir() . '/' . md5(rand()); 
     if(!mkdir($path)) { 
      throw new Exception("mkdir() failed."); 
     } 

     // create a file in that folder 
     $myFile = fopen("$path/myFile.txt", "w"); 
     if(!$myFile) { 
      throw new Exception("Cannot open file handle."); 
     } 
    } 
} 

右の?コードカバレッジは、この行がカバーされていないことを報告します正しいですが、私は、論理的に上にフォルダを作成していますので、それはfopen()がでディスクのように、多分極端な状況を除き(失敗することは不可能と思われる

throw new Exception("Cannot open file handle."); 

100%)。

私はコードカバレッジからコードを無視することができますが、それは不正なものです。 myFile.txtを認識しファイルシステムがファイルを作成できないようにファイルシステムを模擬する方法はありますか?

答えて

9

vfsStreamvirtual filesystemstream wrapperであり、実際のファイルシステムを模擬するための単体テストに役立ちます。 composerからインストールできます。

詳細に:

https://github.com/mikey179/vfsStream

https://phpunit.de/manual/current/en/test-doubles.html

+0

私はmkdir()を渡し、fopen()をvfsで失敗させたいが、どうすれば2つの別々の関数を持たなくてもそれを設定できるのだろうか? –

+0

上記の 'phpunit.de'リンクの' 10.15'の例から始まる 'Mocking the Filesystem'をチェックしてください。 vfsを使用する利点は、元のファイルシステムに実際の依存関係がないことです。 – raidenace

1

はい!

何とかフルパスを注入して、そのメソッドでsys_get_temp_dir()を呼び出さないでください。

存在しないパスが問題を引き起こすはずです。そのためにVFSは必要ありません。

しかし、例外がトリガーされる前にE_NOTICE(またはおそらく警告?)が表示されます。ですから、最初にis_writableをチェックし、falseを返す場合は例外をスローする必要があります。

+0

この状況では、私はそれを注入するかどうかにかかわらず、ベースパスは無関係です。 –

+1

これは関連しています。これを失敗させる最も簡単で一貫した方法は、ベースパスを変更することです。 'sys_get_temp_dir'では、基本パスが常に実パスになるので、VSFを使用することはできません。 – Evert

2

また、関数を2つのメソッドに分割することもできます.1つはパスを作成するメソッド、もう1つはパスを使用するメソッドです。パスが作成されたことを確認するために、個々のテストを行うことができます。第2セットのテストでは、不正なパスを使用しようとすると、例外をチェックしてキャプチャできます。

関連する問題