【问题标题】:Mocking an implementation class with test class within unit test in C#在 C# 中的单元测试中使用测试类模拟实现类
【发布时间】:2015-05-05 21:59:54
【问题描述】:

我正在尝试编写一个简单的单元测试,其中我用接口和实现包装了 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);
    }
}

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

[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);
}

【问题讨论】:

  • 有几种方法:在 FooGenerator 类上,创建一个接受 IPathProvider 的构造函数或创建一个可以设置为 IPathProvider 实例的属性。有关测试接缝的更多详细信息,请参阅 Roy Osherove 撰写的这本精彩书籍 artofunittesting.com/storage/chapters/SampleChapter3.htm 的第 3.4 节。我也建议买这本书。

标签: c# unit-testing interface dependency-injection moq


【解决方案1】:

有几个选项。

接受参数

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

FooProvider 可以有两个构造函数:

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

通用类

将FooProvider改成如下:

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

在非单元测试代码中,您将使用FooProvider&lt;ServicePathProvider&gt;,而对于单元测试,您将使用FooProvider&lt;Mock&gt;。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-30
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 2017-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多