这可以用Moq嘲笑吗?

我正在努力模拟一些外部依赖项,并且遇到一个第三方类的问题,它将构造函数作为另一个第三方类的实例。 希望SO社区可以给我一些指导。

我想创建一个SomeRelatedLibraryClass的模拟实例,它接受它的构造函数SomeLibraryClass的模拟实例。 如何SomeRelatedLibraryClass这种方式模拟SomeRelatedLibraryClass

回购代码……

这是我在测试控制台应用程序中使用的Main方法。

 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 mockMc = new Mock("mock myclass"); mockMc.Setup(i => i.WriteMessage(It.IsAny())) .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的类:

 public class MyClass { private SomeLibraryClass _SLC; public MyClass(string constructMsg) { _SLC = new SomeLibraryClass(constructMsg); } public virtual void WriteMessage(string message) { _SLC.WriteMessage(message); } } 

以下是我正在使用的第三方课程的两个示例( 无法编辑这些课程):

 public class SomeLibraryClass { public SomeLibraryClass(string constructMsg) { Console.WriteLine(string.Concat("SomeLibraryClass Constructor: ", constructMsg)); } public void WriteMessage(string message) { Console.WriteLine(string.Concat("SomeLibraryClass WriteMessage: ", message)); } } public class SomeRelatedLibraryClass { public SomeRelatedLibraryClass(SomeLibraryClass slc) { //do nothing } public void WriteMessage(string message) { Console.WriteLine(string.Concat("SomeRelatedLibraryClass WriteMessage: ", message)); } } 

AFAIK,如果你想要模拟的类不是虚拟或接口 – 你不能用Moq模拟它。 如果你的第三方图书馆没有实施他们的课程,我认为你运气不好。

我建议使用网关模式。 而不是直接依赖于SomeRelatedLibraryClass,创建一个接口ISomeRelatedLibraryClassGateway。 公开您需要使用ISomeRelatedLibraryClassGateway上相同签名的方法调用的所有SomeRelatedLibraryClass方法。

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

现在,您的应用程序中依赖于SomeRelatedLibraryClass的类现在可以依赖于ISomeRelatedLibraryClassGateway,并且此接口很容易被模拟。 SomeRelatedLibraryClassGateway类并不真正需要unit testing; 它所做的只是通过电话。 它确实需要在function测试中进行测试,但您可以在没有模拟的情况下进行function测试。

希望这可以帮助。