C# 这可以用最小起订量来嘲弄吗?

C# 这可以用最小起订量来嘲弄吗?,c#,.net,unit-testing,mocking,moq,C#,.net,Unit Testing,Mocking,Moq,我正在模拟一些外部依赖项,并且在一个第三方类中遇到了问题,这个第三方类的构造函数中包含了另一个第三方类的实例。希望SO社区能给我一些指导 我想创建一个SomeRelatedLibraryClass的模拟实例,它接受它的构造函数SomeLibraryClass的模拟实例。我怎样才能用这种方式模拟某个相关的库类 回购代码… 下面是我在测试控制台应用程序中使用的一个主要方法 public static void Main() { try { SomeLibraryCla

我正在模拟一些外部依赖项,并且在一个第三方类中遇到了问题,这个第三方类的构造函数中包含了另一个第三方类的实例。希望SO社区能给我一些指导

我想创建一个
SomeRelatedLibraryClass
的模拟实例,它接受它的构造函数
SomeLibraryClass
的模拟实例。我怎样才能用这种方式模拟某个相关的库类

回购代码…

下面是我在测试控制台应用程序中使用的一个主要方法

public static void Main()
{
    try
    {
        SomeLibraryClass slc = new SomeLibraryClass("direct to 3rd party");
        slc.WriteMessage("3rd party message");
        Console.WriteLine();

        MyClass mc = new MyClass("through myclass");
        mc.WriteMessage("myclass message");
        Console.WriteLine();

        Mock<MyClass> mockMc = new Mock<MyClass>("mock myclass");
        mockMc.Setup(i => i.WriteMessage(It.IsAny<string>()))
            .Callback((string message) => Console.WriteLine(string.Concat("Mock SomeLibraryClass WriteMessage: ", message)));

        mockMc.Object.WriteMessage("mock message");
        Console.WriteLine();
    }
    catch (Exception e)
    {
        string error = string.Format("---\nThe following error occurred while executing the snippet:\n{0}\n---", e.ToString());
        Console.WriteLine(error);
    }
    finally
    {
        Console.Write("Press any key to continue...");
        Console.ReadKey();
    }
}
以下是我正在使用的两个第三方类的示例(您不能编辑这些类):


好了,如果你试图模拟的类不是虚拟的或者不是接口,你就不能用Moq来模拟它。如果您的第三方库没有实现它们的类,我认为您运气不好。

我建议使用该模式。与其直接依赖于某个RelatedLibraryClass,不如创建一个接口异构RelatedLibraryClassGateway。公开所有需要使用异构相关LibraryClassGateway上具有相同签名的方法调用的RelatedLibraryClass方法

public interface ISomeRelatedLibraryClassGateway {
  void WriteMessage(string message);
}
然后创建一个将所有调用路由到第三方类的实现:

public class SomeRelatedLibraryClassGateway : ISomeRelatedLibraryClassGateway {
  private readonly SomeRelatedLibraryClass srlc;
  public SomeRelatedLibraryClassGateway(SomeRelatedLibraryClass srlc) {
    this.srlc = srlc;
  }

  void ISomeRelatedLibraryClassGateway.WriteMessage(string message) {
    srlc.WriteMessage(message);
  }
}
现在,应用程序中依赖于某个RelatedLibraryClass的类可以改为依赖于异构RelatedLibraryClassGateway,这个接口很容易模拟。类SomeRelatedLibraryClassGateway实际上不需要单元测试;它所做的就是把电话传过去。它确实需要在功能测试中进行测试,但是您可以在没有模拟的情况下进行功能测试


希望这有帮助。

实际上,问题是我需要模拟SomeRelatedLibraryClass,它作为SomeLibraryClass类型的参数。我不清楚网关模式如何让我更容易地模拟那个类。在集成外部依赖项时,我通常使用网关模式,但在本例中,我省略了接口定义和实现,因为我认为它与问题无关。重点是避免模拟某些RelatedLibraryClass。使用网关模式可以避免模拟某些RelatedLibraryClass,因为(大部分)代码并不直接依赖于它。这是一个重构代码以便更容易测试的示例。
public interface ISomeRelatedLibraryClassGateway {
  void WriteMessage(string message);
}
public class SomeRelatedLibraryClassGateway : ISomeRelatedLibraryClassGateway {
  private readonly SomeRelatedLibraryClass srlc;
  public SomeRelatedLibraryClassGateway(SomeRelatedLibraryClass srlc) {
    this.srlc = srlc;
  }

  void ISomeRelatedLibraryClassGateway.WriteMessage(string message) {
    srlc.WriteMessage(message);
  }
}