在 C# 的单元测试中使用测试 class 模拟实现 class

Mocking an implementation class with test class within unit test in C#

我正在尝试编写一个简单的单元测试,其中我用接口和实现包装了 HttpContext.Current.Server.MapPath。我不确定实施是否在正确的地方。

public class FooGenerator
{
    ServerPathProvider serverPathProvider = new ServerPathProvider();

    public string generateFoo()
    {
        BarWebService bws = new BarWebService(serverPathProvider.MapPath("~/path/file"));
        return stuff;
    }
}


public class ServerPathProvider : IPathProvider
{
    public string MapPath(string path)
    {
        return HttpContext.Current.Server.MapPath(path);
    }
}

在测试中我有自己想要使用的实现,但我不知道如何在单元测试期间将其注入到真实的 class 中。

[TestClass()]
public class FooGeneratorTests
{
    [TestMethod()]
    public void generateFooTest()
    {
        FooGenerator fg = new FooGenerator();

        //Some kind of mock dependency injection
        Mock<IPathProvider> provider = new Mock<IPathProvider>();
        //stub ServerPathProvider object with provider mock

        string token = fg.generateFoo;
        Assert.IsNotNull(token);
    }
}

public class TestPathProvider : IPathProvider
{
    public string MapPath(string path)
    {
        return Path.Combine(@"C:\project\", path);
    }
}

最后,为了以防万一,这是我的界面。基本上我只想根据我是否进行单元测试来交换两个实现。这是我的第一个单元测试,其中很多内容对我来说都是新的。对不起,如果我遗漏了一些基本的东西,但我已经研究了一段时间的堆栈溢出,但找不到执行这一部分的步骤。

public interface IPathProvider
{
    string MapPath(string path);
}

有几个选项。

接受参数

一般来说,您希望 FooProvider 有一个 IPathProvider 而不是 ServicePathProvider 作为它的 servicePathProvider 成员变量。

FooProvider 可以有两个构造函数:

  1. 实例化servicePathProvider = new ServicePathProvider();
  2. 的默认构造函数
  3. 实例化的非默认构造函数接受 IServiceProvider 作为参数并将 servicePathProvider 设置为该参数。

通用 类

更改FooProvider如下:

public class FooProvider<T> where T : IServiceProvider, new()

在非单元测试代码中,您将使用 FooProvider<ServicePathProvider>,对于单元测试,您将使用 FooProvider<Mock>

这使得 FooProvider 接受泛型类型 T,它是 IServiceProvider 的子类型 并且 具有默认构造函数(即 new() 部分)在 where 子句中。