IO操作(この場合はファイルシステム)を多用するプロジェクトにテストを導入しています。システムは常にファイルを開いたり閉じたり、ファイルが存在するかどうかをチェックしたり、削除したりします。 。
すぐに、通常のモックはあまり役に立たないことが明らかになりました。テストのセットアップと推論が難しくなるからです。一方、偽のファイルシステムを作成するのは素晴らしいことであり、セットアップは非常に簡単だと思います。
Rubyみんながもう一度やったようです。Rubyで私がまさに求めていることは、 http://ozmm.org/posts/fakefs.html です。
Javaに似たようなものはありますか?
Googleには、Java 7のFileSystemProvider .. プロジェクトはjimfs と呼ばれる)のオープンソースのメモリ内実装があります。
Java 6またはそれ以前のバージョンを使用する場合、代替手段があります。以前に Apache Commons VFS を使用したことがあります。言及された別の回答者はJava 7。
pre-loaded いくつかのファイルシステム実装が付属しています:ファイル、RAM、S/FTP、Jarをいくつか挙げます。 S3のプラグイン も見ました。
Java 6以前では、File
やFileInputStream
などのクラスがJavaの異なる「仮想ファイルシステム」にディスパッチする方法を提供しないため、困難です。スペース。
Java 7では、仮想ファイルシステムのサポートがあります。 カスタムファイルシステムプロバイダーの開発 を参照してください。これであなたがやりたいことができるかどうかはわかりませんが、探し始めるには良い場所です。
えー実際には偽のファイルシステムは存在しないように見えるため、自分で最小限の実装を実装するだけだと思います。 FileSystemProviderを使用しても何も勝ちません
実際、FileSystemProviderを使用して勝ちます。
(オープンソースライセンスでリリースされた場合)あなたの立場にある他の人にとって、そして他の目的のために非常に役立つものを実装します。
他の誰かが現在作業している可能性のあるFileSystemProviderに切り替えることにした場合は、自分で簡単に作成できます。
JUnit パッケージの_org.junit.rules.TemporaryFolder
_を使用できます。
TemporaryFolderルールを使用すると、テストメソッドの終了時に(パスするか失敗するかに関係なく)削除されることが保証されているファイルとフォルダーを作成できます。
例:
_final TemporaryFolder testFolder = new TemporaryFolder();
testFolder.create();
final Path filePath = testFolder.newFile("input.txt").toPath();
final Path dirPath = testFolder.newFolder("subfolder").toPath();
_
または、.toPath()
部分を終了します。
_final File filePath = testFolder.newFile("input.txt");
_
File
の代わりにOutputStream
を使用するようにAPIを変更することにより、「どこかでデータを書き込む」という意図を使用して、File
の使用を抽象化できます。実動コードではFileOutputStream
ですが、テストから ByteArrayOutputStream
を渡します。 ByteArrayOutputStream
はメモリ内ストリームであるため、非常に高速であり、メソッドを使用するだけで内容を簡単に検査できます。テストに最適です。データをreadしたい場合は、対応するByteArrayInputStream
もあります。
通常、ファイルシステムは非常に高速です。テストで大量のファイルI/Oを実行していない限り、気にしません。
Java File
オブジェクトを作成すると、notディスク上にファイルが作成されます。コードはディスクを変更しません:
File f = new File("somepath"); // doesn't create a file on disk
Jimfs 、Googleによる、メモリ内NIOファイルシステムであり、テストに最適です。
MockFTPServer は、いくつかの偽のファイルシステム実装を持っているようです(Unix/Windows)
これらの偽のファイルシステムの実装は、FTPの概念とはまったく別に使用できるようです。私は今あなたが概説したのとまったく同じ目的でこれを試しています。
特定のフレームワークについてはわかりませんが、OOPの観点からの一般的なアプローチは、ファイルアクセスコード(豊富なインターフェイス!)と、おそらく一般的な操作の使用を容易にします。次に、現在テストしているコードの1つ下のレイヤーをモックし、それが本質的に偽のファイルシステムになります(または、少なくともテストしているコードは別の方法ではわかりません)。
依存性注入フレームワークを使用してこれを処理する場合、インターフェイスの偽装実装のコンポーネントを切り替える機能が容易になります。制御の反転のパターンに従う場合、依存関係をテストするクラスのコンストラクターに渡すと、テストも簡単になります。
public interface IFileSystem {
IFileHandle Load(string path);
//etc
}
public class ClassBeingTested {
public ClassBeingTested(IFileSystem fileSystem) {
//assign to private field
}
public void DoSomethingWithFileSystem() {
//utilise interface to file system here
//which you could easily mock for testing purposes
//by passing a fake implementation to the constructor
}
}
私はJavaが正しい、私は長い間書かれていませんJava、しかしあなたはドリフトを手に入れることを望みます。願わくば過小評価していません。ここでの問題と過度に単純化です!
もちろん、これはすべて、真のユニットテスト、つまり、システム全体ではなく、可能な限り最小のコードユニットのテストを意味することを前提としています。統合テストには、異なるアプローチが必要です。
ArquillianプロジェクトのShrinkWrap メモリFileSystemに準拠したNIOを含めるように見える
次の操作を行うことで、メモリ内のシンプルなFileSystemを作成できます。
FileSystem fs = ShrinkWrapFileSystems.newFileSystem(ShrinkWrap.create(GenericArchive.class))
私はグーグルで「Fake Java FileSystem」を見つけました。残念ながらこれは私が見つけたすべてです。だから私はこの偽のFileSystemを自分で書きました: https://github.com/dernasherbrezon/mockfs
ファイルの読み取り/書き込み中にIOExceptionsをシミュレートするために使用しています。 IOExceptionは、たとえば「ディスク領域がない」ために発生する可能性がありますが、これは他の方法ではほとんど不可能です。