0

テストしたい次のコードがあります。

public class DirectoryProcessor
{
    public string DirectoryPath
    {
        get;
        set;
    }

    private FileSystemWatcher watcher;

    public event EventHandler<SourceEventArgs> SourceFileChanged;

    protected virtual void OnSourceFileChanged(SourceEventArgs e)
    {
        EventHandler<SourceEventArgs> handler = SourceFileChanged;
        if(handler != null)
        {
            handler(this, e);
        }
    }

    public DirectoryProcessor(string directoryPath)
    {
        this.DirectoryPath = directoryPath;
        this.watcher = new FileSystemWatcher(directoryPath);
        this.watcher.Created += new FileSystemEventHandler(Created);
    }

    void Created(object sender, FileSystemEventArgs e)
    {
        // process the newly created file
        // then raise my own event indicating that processing is done
        OnSourceFileChanged(new SourceEventArgs(e.Name));
    }
}

基本的に、私は次のことを行うNUnitテストを書きたいと思います。

  1. ディレクトリを作成する
  2. セットアップDirectoryProcessor
  3. いくつかのファイルをディレクトリに書き込みます(経由File.WriteAllText()
  4. DirectoryProcessor.SourceFileChanged手順3で追加したファイルごとに1回起動したことを確認します。

これを実行して手順3の後に追加しようとしThread.Sleep()ましたが、タイムアウトを正しく取得するのは困難です。ディレクトリに書き込んだ最初のファイルは正しく処理されますが、2番目のファイルは処理されません(タイムアウトが60秒に設定されています)。このように動作させることができたとしても、テストを書くのはひどい方法のようです。

誰かがこの問題に対する良い解決策を持っていますか?

4

2 に答える 2

2

通常、ファイルシステムとの相互作用のテストに関心があり、実際に操作を実行するフレームワーククラスとメソッドをテストする必要はありません。

クラスに抽象化レイヤーを導入すると、ユニットテストでファイルシステムをモックして、実際にファイルシステムを操作しなくても、相互作用が正しいことを確認できます。

テスト以外では、「実際の」実装は、作業を完了するためにこれらのフレームワークメソッドを呼び出します。

はい、理論的にはその「実際の」実装を統合テストする必要がありますが、実際にはリスクが低く、大きな変更の影響を受けず、数分間の手動テストで検証できる必要があります。オープンソースのファイルシステムラッパーを使用する場合は、安心のためにこれらのテストが含まれる場合があります。

単体テストのためにC#でファイルシステムをどのようにモックアウトしますか?を参照してください。

于 2012-08-30T20:17:41.387 に答える
0

このクラスを使用する別のオブジェクトをテストする場合、私の答えは関係ありません。

ユニットテストを操作に書き込むときは、ManualResetEventを使用することを好みます

単体テストは次のようになります。

     ...
     DirectoryProcessor.SourceFileChanged+=onChanged;
     manualResetEvent.Reset();
     File.WriteAllText();
     var actual = manualResetEvent.WaitOne(MaxTimeout);
     ...

manualResetEventがManualResetEventであり、MaxTimeoutがTimeSpanである場合(私のアドバイスでは常にタイムアウトを使用します)。現在、「onChanged」がありません。

     private void onChanged(object sender, SourceEventArgs e)
     {
          manualResetEvent.Set();
     }    

これがお役に立てば幸いです

于 2012-08-30T20:36:24.403 に答える