2016-05-17 54 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));