我正在努力模拟一些外部依赖项,并且遇到一个第三方类的问题,它将构造函数作为另一个第三方类的实例。希望SO社区可以给我一些指导。
我想创建一个SomeRelatedLibraryClass
的模拟实例,它将构造函数作为SomeLibraryClass
的模拟实例。我怎样才能以这种方式模仿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<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的类:
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));
}
}
答案 0 :(得分:10)
我建议使用Gateway模式。而不是直接依赖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类实际上不需要单元测试;它所做的就是通过电话。 需要在功能测试中进行测试,但是你可以在没有模拟的情况下进行功能测试。
希望这有帮助。
答案 1 :(得分:2)
AFAIK,如果你试图模拟的类不是虚拟或界面 - 你不能用Moq模拟它。如果你的第三方图书馆没有实施他们的课程,我认为你运气不好。