0

基本的にはこんな状態です。私は次のものを持っています:

public IService Service { get; set; } //Set to MyMockedService class.

public Boolean DoFoo()
{
    //possible other ways of returning true/false...

    Boolean success = true;

    //Get FileInfo[] items

    foreach (var item in items)
        DoOtherFoo(item);
}

public Boolean DoOtherFoo(FileInfo fileInfo)
{
    String filepath = //manipulate fileInfo.FullName;

    Byte[] file = Service.GetFile(filepath)
    try
    {
        WriteBinaryFile(filepath, file); //How can I force file writing to throw an exception
    }
    catch (Exception)
    {
        return false;
    }
}

基本的に、DoFoo() のテストでは、true/false を返すパスがたくさんあります。最後のファイルを除いてすべてのユニットをテストしました...ファイルを書き込もうとし、何らかの理由でファイルの1つでも書き込めない場合、失敗してfalseを返します。最初は、「bad*file」などの不適切なファイル名を設定しようとすると、WriteFile で例外がスローされると考えましたが、不正な文字を使用して FileInfo オブジェクトを作成できないため、そこまで到達しませんでした。だから私はそれを作成する別の方法を探しているので、ファイルを書き込むことが不可能になり、偽を取り戻すことができます。

4

5 に答える 5

4

良い単体テストは孤立したものです。これは、それらがどの環境 (ファイル、データベース、ネットワークなど) からも完全に独立していることを意味します。コードでファイルを使用してデータを保存する場合は、何らかのインターフェイスで非表示にする必要があります。運用コードとテスト コードでは異なる実装が使用されます。プロダクションは実際にファイルへの書き込みを行い、テストはそれをエミュレートするだけです。

public interface IStorage
{
  bool StoreToFile(string path, string file, byte[] data);
}

public class Storage : IStorage
{
  public bool StoreToFile( ... )
  {
     return WriteToFile( ... );
  }
}

public class StorageMock : IStorage
{
   public bool StoreToFile (...)
   {
      return false;  //or true, depends on you test case
   }
}

テストでは、実際の実装を偽の実装に「置き換える」ことができます。これはモッキングと呼ばれます。

「Inversion of Control」と呼ばれる配慮したデザイン。また、依存性注入 (StructureMap、Ninject、Wisdor) を通じて「Investion of Control」を使用できるフレームワークも多数あります。

于 2011-01-12T16:28:31.790 に答える
3

WriteBinaryFileこれと同じ方法ですかclass

この唯一の責任でオブジェクトを作成できますが、抽象化から始めます。

public interface IBinaryFileWriter
{
    void WriteBinaryFile(string filepath, Byte[] file);
}

これで、できればコンストラクターの引数として、テストしているクラスにこの依存関係を注入できます。

IBinaryFileWriterアプリケーションでは、現在のメソッドとまったく同じことを行う の実装を使用します。

ただし、テストでは、例外をスローするように構成できるモックを提供できます。

于 2011-01-12T16:27:35.563 に答える
1

単体テストではSystem.IO.File.Open(...)FileShareset toで使用できますNone。他のプロセスは、そのファイルを開くことができません。

于 2011-01-12T16:22:50.037 に答える
0

FileInfo の ctor の逆コンパイル コードは次のとおりです。

public FileInfo(string fileName)
{
    if (fileName == null)
    {
        throw new ArgumentNullException("fileName");
    }
    base.OriginalPath = fileName;
    string fullPathInternal = Path.GetFullPathInternal(fileName);
    new FileIOPermission(FileIOPermissionAccess.Read, new string[] { fullPathInternal }, false, false).Demand();
    this._name = Path.GetFileName(fileName);
    base.FullPath = fullPathInternal;
}

そのため、FileInfo を作成した後、リフレクションによって FullPath と OriginalPath を無効なファイルパスに設定し、WriteBinary が exception をスローするようにすることができます。

そのように:

 FileInfo info = new FileInfo("c:\\1.txt");
 info.GetType().BaseType.GetField(
      "FullPath", 
      BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.Instance)
   .SetValue(info, "invalidpath");
 info.GetType().BaseType.GetField(
      "OriginalPath", 
       BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.Instance)
   .SetValue(info, "invalidpath");
于 2011-01-12T16:43:40.717 に答える
0

WriteBinaryFile の内部に依存します。より詳細なレベルで WriteBinaryFile をテストする必要があります。私はそれがあなたの機能だと思います...私は頭の上からそれを認識していません.

于 2011-01-12T16:22:40.573 に答える