使用File.Exists进行单元测试功能

qwe*_*123 0 c# unit-testing mocking

我该如何对这类功能进行单元测试?当然我无法创建真正的文件,我无法对Example类和Func进行任何更改以使其更容易测试.

正如我发现的那样,Exists使用流行的免费框架(如moq)来模拟静态是不可能的.我找到了一些模拟文件系统的框架,如System.IO.Abstractions(https://github.com/tathamoddie/System.IO.Abstractions),但在我发现的所有样本中,方法(如此处CreateDirectoryExists)都是从模拟中调用的对象,我不知道如何使它适应这种方法(如果可能的话).

public class Example
{
    public int Func()
    {
        if(System.IO.File.Exists("some hard-coded path"))
        {
            return 1;
        }
        else
        {
            return 2
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

g t*_*g t 5

如何在测试中创建一个FileWrapper类并将其作为依赖项传递?

public class Example
{
    private IFileWrapper _fileWrapper;

    public Example()
        : this(new FileWrapper())
    {
    }    

    public Example(IFileWrapper fileWrapper)
    {
        _fileWrapper = fileWrapper;
    }

    public int Func()
    {
        if (_fileWrapper.Exists("some path")
        {
            // etc
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后定义FileWrapper为:

internal class FileWrapper : IFileWrapper
{
    public bool Exists(string path)
    {
        return File.Exists(path);
    }
}
Run Code Online (Sandbox Code Playgroud)

和接口IFileWrapper为:

public interface IFileWrapper
{
    bool Exists(string path);
}
Run Code Online (Sandbox Code Playgroud)

然后你的测试可以创建一个模拟IFileWrapper并将其传递给你测试的类(在这里使用Moq):

[TestMethod]
public void Func_ShouldCheckFileExists()
{
    // Arrange
    var mockFileWrapper = new Mock<IFileWrapper>();
    mockFileWrapper.Setup(_ => _.Exists(It.IsAny<string>())).Returns(true);

    var example = new Example(mockFileWrapper.Object);

    // Act
    int returnValue = example.Func("test path");

    // Assert
    Assert.Equals(returnValue, 1);
}
Run Code Online (Sandbox Code Playgroud)

这是一个更多的工作,但你可以建立一个这样的包装器的库,并在你的代码库中重用它们.

如果你真的无法修改你的代码,那么看看微软的Moles项目,或者更新的Fakes项目可能对你有帮助.