2016-05-17 55 views
3

我正在使用Moq框架設置單元測試。單元測試嘲笑框架迫使你在編程的方式嗎?

我有描述像這樣的類的接口:

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

爲了保證RemoveSource-方法被稱爲我實現了一個基類,其中的刪除被稱爲在dispose方法。

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自己調用。通常,您可以使用Moq來驗證對SUT的依賴關係的調用。

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));