在下面的示例中,我想测试TestMe.DoSomething()函数。

我想模拟此方法中使用的ISomething接口,并使其返回不同的值(取决于特定的单元测试。)

在现实生活中,ISomething接口最终会调用昂贵的第三方资源-我绝对不想只调用真实的ISomething

这是示例结构:

class TestMe
{
    public void DoSomething()
    {
        ISomething s = SomethingFactory();
        int i = s.Run();

        //do things with i that I want to test
    }

    private ISomething SomethingFactory()
    {
        return new Something();
    }
}

interface ISomething
{
    int Run();
}

class Something : ISomething
{
    public int Run()
    {
        return 1;
    }
}


这是无效的代码:

        var fakeSomething = new Mock<ISomething>();
        var testMe = new TestMe();
        Mock.Get(testMe).Setup(p => p.SomethingFactory()).Returns(fakeSomething.Object);
        testMe.DoSomething();


因为SomethingFactory()private,所以无法将该方法的返回值设置为所需的值。

关于如何解决这个问题有什么建议吗?

最佳答案

使工厂成为完整的接口/类,并从TestMe中删除SomethingFactory方法。

public interface ISomethingFactory {
  ISomething MakeSomething();
}

public sealed class SomethingFactory {
  public ISomething MakeSomething() {
    return new Something();
  }
}

class TestMe
{
    private readonly ISomethingFactory _somethingFactory;

    public TestMe(ISomethingFactory somethingFactory) {
      _somethingFactory = somethingFactory;
    }

    public void DoSomething()
    {
        ISomething s = _somethingFactory.MakeSomething();
        int i = s.Run();

        //do things with i that I want to test
    }
}


这将允许您模拟ISomethingFactory以返回ISomething的模拟。

尽管我认为您可能会反对这种解决方案,因为它太过彻底了,但我认为它比制作一个没有被成员密封的课程要好得多,因为只有虚拟的原因是测试。

10-04 10:27