如何对这个C#扩展方法进行单元测试?

3

我不确定如何模拟一个测试这个的情况。我是否需要在文件系统上实际创建一个文件?

public static void DeleteIfExists(this FileInfo fileInfo)
{
   if (fileInfo.Exists)
   {
      fileInfo.Delete();
   }
}

如果有人更改了实现并破坏了它,它可能会失败。 :-) - Mike Cole
我会创建一个文件。就像测试数据库时,我首先插入一条新记录,这样我就有了一个虚拟的记录来测试删除方法... - BrunoLM
@BrunoLM - 你为什么要这样做,而不是使用RhinoMocks呢? - Mike Cole
2
这是一个尝试编写单元测试,实际上却是集成测试的例子吗? - Mitch Wheat
@Mike 我觉得这只是一个简单的任务,我会保持它的简单性。除非你的服务器有一些限制防止你立即编写和删除文件,否则我不会仅仅为此使用RhinoMocks。但如果你打算在整个项目中使用RhinoMocks,那就去做吧 :P - BrunoLM
2
摆脱扩展方法,直接调用FileInfo.Delete。如果文件不存在,FileInfo.Delete不会执行任何操作。请参阅http://msdn.microsoft.com/en-us/library/system.io.fileinfo.delete.aspx。 - TrueWill
1个回答

8

我会使用一个模拟框架,例如RhinoMocks

[Test]
public void ShouldDeleteAFileWhenItExists()
{
    var mockInfo = MockRepository.GenerateMock<FileInfo>();
    mockInfo.Expect( i => i.Exists ).Return( true ).Repeat.Once();
    mockInfo.Expect( i => i.Delete() ).Repeat.Once();

    var extensions = new FileInfoExtensions();

    extensions.DeleteIfExists( mockInfo );

    mockInfo.VerifyAllExpectations();
}

[Test]
public void ShouldNotDeleteAFileWhenItDoesNotExist()
{
    var mockInfo = MockRepository.GenerateMock<FileInfo>();
    mockInfo.Expect( i => i.Exists ).Return( false ).Repeat.Once();
    mockInfo.Expect( i => i.Delete() ).Repeat.Never();

    var extensions = new FileInfoExtensions();

    extensions.DeleteIfExists( mockInfo );

    mockInfo.VerifyAllExpectations();
}

其他测试用例包括当Delete抛出异常时等情况。


2
虽然这样做可以工作,但它会暴露被测试方法的内部逻辑:与外界的契约是“如果文件存在,则删除该文件”,但我们并不受如何实现的限制...如果一个实现调用了两次Exists()会怎么样?这些测试强制要求方法以某种方式实现,这在我看来似乎是错误的... - Mitch Wheat
1
测试 Delete 成员是否被调用感觉不对。如果该方法更改为获取文件的完整路径,然后只调用 File.Delete(path),那么这肯定是正确的实现... - Tomas Petricek
1
@tvanfosson:我认为这是对测试的滥用。测试不应依赖于特定的内部实现。 - Mitch Wheat
1
@Tomas - 为什么?记住这是一个扩展方法。我们的目标是确保它与我们想要的类进行交互,而不是找出一种可能不使用我们正在扩展的类的方式来删除文件。我们只想为使用这个类的一些代码提供一个快捷方式,并测试驱动该行为。 - tvanfosson
2
@Mitch - 这是一个扩展方法!我们不是在尝试发明删除文件的新方法,而是在尝试减少代码复制量,用于检查我们是否使用扩展的类对象删除文件之前它是否存在。在这种情况下,我们关心的是特定方法的调用,而不是文件是否实际被删除。我们相信我们扩展的类能够正常工作。 - tvanfosson
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接