在C#中模拟StreamReader以进行单元测试

亚历克斯

我有这种格式的代码:

public void parseFile(string filePath)
{
    using (var reader = new StreamReader(@filePath))
    {
        //Do something
    }
}

我现在想对代码进行单元测试,但不希望单元测试实际访问文件系统,因为如果实际文件不存在,这会使它们不可靠。

为了防止streamreader访问文件系统,我需要对其进行模拟。我的理解是,我只能模拟实现接口的类。

因此,我可以看到的一个解决方案是为其创建包装类和接口Streamreader,然后可以对其进行模拟。

我的问题分为两个部分:

  1. 这是解决这个问题的唯一方法吗?

  2. 为了方便进行单元测试,在项目中添加额外的层是否正确?如果我在全球范围内遵循这一原则,我会增加很多额外的课程吗?

艾丁

上面的示例的问题在于,该parseFile方法正在创建自己的实例StreamReader,因此模拟StreamReader不会真正起作用,因为:

  1. 您无权访问该对象。
  2. 您只能模拟interfaces或标记为的类的成员virtual

相反,您可以做的是创建一个接口IFileManager,使用一个称为的方法将其称为参数StreamReader

public interface IFileManager
{
     StreamReader StreamReader(string path);
}

然后在另一个类(我们称之为Foo)中,该类包含ParseFile您上面发布方法:

public class Foo 
{
    IFileManager fileManager;

    public Foo(IFileManager fileManager)
    {
        this.fileManager = fileManager;
    }

    public void parseFile(string filePath)
    {
        using (var reader = fileManager.StreamReader(filePath))
        {
            //Do something
        }
    }
}

现在,您可以模拟IFileManager interface和其StreamReader方法,可以将此模拟的实例注入到Foo类中,以供ParseFile方法使用。

现在您的代码将依赖于抽象而不是具体的实现,我们已经反转了依赖关系,这使我们能够模拟依赖关系并隔离我们要实际测试的代码。


创建模拟对象的粗略演示

public static void Main()
{
    Mock<IFileManager> mockFileManager = new Mock<IFileManager>();
    string fakeFileContents = "Hello world";
    byte[] fakeFileBytes = Encoding.UTF8.GetBytes(fakeFileContents);

    MemoryStream fakeMemoryStream = new MemoryStream(fakeFileBytes);

    mockFileManager.Setup(fileManager => fileManager.StreamReader(It.IsAny<string>()))
                   .Returns(() => new StreamReader(fakeMemoryStream));

    Foo foo = new Foo(mockFileManager.Object);

    string result = foo.ParseFile("test.txt");

    Console.WriteLine(result);
}

public interface IFileManager
{
    StreamReader StreamReader(string path);
}

public class Foo
{
    IFileManager fileManager;

    public Foo(IFileManager fileManager)
    {
        this.fileManager = fileManager;
    }

    public string ParseFile(string filePath)
    {
        using (var reader = fileManager.StreamReader(filePath))
        {
            return reader.ReadToEnd();
        }
    }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

模拟WifiManager进行Android单元测试

如何模拟HttpClientBuilder进行单元测试

在C#中对私有方法进行单元测试

您如何在C#中模拟文件系统以进行单元测试?

C#单元测试,模拟存储过程

模拟HttpActionContext进行单元测试

模拟SparkSession进行单元测试

模拟@AuthenticationPrincipal以进行单元测试

如何在C#中对嵌套的“ using”语句进行单元测试?

如何在C#中对PowerShell Core二进制cmdlet进行单元测试

尝试从获取中模拟响应主体以进行单元测试

如何使用xUnit对C#事件进行单元测试

使用Mock对C#中的更新方法进行单元测试

如何在单元测试C#中模拟AuthenticationContext.AcquireTokenAsync

C#单元测试模拟服务忽略返回

如何在C#中以CQRS模式对命令处理程序进行单元测试

在C#中,使用ILogger对静态方法进行单元测试的静态方法ILoggerFactory为空

模拟函数不会在C#单元测试中引发异常

模拟服务中的方法进行单元测试

模拟__init __()进行单元测试

在Perl中存根并模拟subrotine以进行单元测试

如何在模拟方法中对函数进行单元测试

模拟HttpRequestException进行单元测试

如何在C#中对URL有效进行单元测试?

模拟控制器进行单元测试,无需任何服务引用 C#

如何使用 Visual Studio 单元测试框架或 NUnit 框架在 C# 中模拟对象?

使用没有接口的模拟进行 C# 单元测试

通过在 C# 中使用 Moq 模拟外部 DLL 进行单元测试

c#中单元测试的问题