2016-05-17 5 views
3

私はMoqフレームワークを使って単体テストをセットアップしています。私は削除がdisposeメソッドで呼び出される基本クラスを実装呼ばれるユニット・テスト・モッキング・フレームワークは、プログラミングの方法であなたを強制しますか?

public interface ISourceFileLocation : IFileLocation, IDisposable 
{ 
    bool RemoveAfterTransfer { get; set; } 
    void RemoveSource(); 
    //..... 
} 

RemoveSource-法を確保するために:

私はそうのようなクラスを記述するインタフェースを有しています。

public abstract class SourceFileBase : ISourceFileLocation 
{ 
    //...... 

    public bool RemoveAfterTransfer { get; set; } 

    public void RemoveSource() 
    { 
     if (File.Exists(Uri.AbsolutePath)) 
     { 
      File.Delete(Uri.AbsolutePath); 
     } 
    } 

    public void Dispose() 
    { 
     if (this.RemoveAfterTransfer) 
      this.RemoveSource(); 
    } 
} 

テストのために、私は具体的なクラスから継承する必要がある基底クラスでのテストを実施したいので、デフォルトの実装は、ありませんISourceFileLocationをあざけります。

私のテストでは、RemoveSource-Methodがバーチャルで、メソッドが呼び出されることを保証するという私の考えを破ると予想しています。

これはフレームワークの欠如ですか、これをテストする優れたフレームワークや方法があるのでしょうか、これは私のコードに問題があり、私のデザインを再考すべきでしょうか?

種類について

testmethods:

[TestCategory("Source")] 
    [TestMethod] 
    public void CheckIfRemoveSourceMethodIsCalled() 
    { 
      //ARRANGE 
      var mockSourceLocation = new Mock<SourceFileBase>(); 
      mockSourceLocation.Object.RemoveAfterTransfer = true; 
      mockSourceLocation.Setup(x => x.RemoveSource()); 
      //ACT 
      mockSourceLocation.Object.Dispose(); 
      /ASSERT 
      mockSourceLocation.VerifyAll(); 
    } 

    [TestCategory("Source")] 
    [TestMethod] 
    public void CheckIfRemoveSourceMethodIsNotCalled() 
    { 
      //ARRANGE 
      var mockSourceLocation = new Mock<SourceFileBase>(); 
      mockSourceLocation.Object.RemoveAfterTransfer = false; 
      //ACT 
      mockSourceLocation.Object.Dispose(); 
      //ASSERT 
      mockSourceLocation.Verify(x=>x.RemoveSource(), Times.Never); 
    } 

答えて

6

私はあなたがテスト(SUT)の下で、お使いのシステムの同じモックオブジェクトを使用している、とあなたの行動の検証を実行するため、この例では部品番号を悪用することができると思います。あなたのテストは基本的にSourceFileBaseがそれ自身を呼び出すかどうかをチェックしています。通常、SUTの依存関係への呼び出しを確認するには、Moqを使用します。

SourceFileBaseのコードは、Fileクラスの静的メソッドを直接使用しているため、単体テストには適していません。ユニットをテスト可能にするには、何らかの理由でこれを抽象化する必要があります(たとえば、this questionを参照)。

そう
public abstract class SourceFileBase : ISourceFileLocation 
{ 
    private readonly IFileSystem _fileSystem; 

    public SourceFileBase(IFileSystem fileSystem) 
    { 
     _fileSystem = fileSystem; 
    } 

    ... 

    public void RemoveSource() 
    { 
     _fileSystem.DeleteFile(Uri.AbsolutePath); 
    } 

    public void Dispose() 
    { 
     RemoveSource(); 
    } 
} 

あなたはDispose()RemoveSource()の両方がファイルを削除することをテストすることが可能になります。

// Arrange 
var mockFileSystem = new Mock<IFileSystem>(); 
var sut = new Mock<SourceFileBase>(mockFileSystem.Object); 
sut.RemoveAfterTransfer = true; 
sut.Uri = myTestUri; 

// Act 
sut.Dispose(); 

// Assert 
mockFileSystem.Verify(f => f.DeleteFile(myTestUri.AbsolutePath)); 
関連する問題