C# 如何使用mock.Of<;模拟构造函数中包含参数的类&燃气轮机;语法?

C# 如何使用mock.Of<;模拟构造函数中包含参数的类&燃气轮机;语法?,c#,.net,unit-testing,moq,C#,.net,Unit Testing,Moq,这向我展示了如何模拟构造函数中包含参数的类。下面是关于的Mock.的一个示例,但它没有显示如何使用函数语法模拟构造函数 public class MyClass { public MyClass(IDependency1 dep1, IDependency2 dep2, IDependency3 dep3) {} public ReturnType MyNewMethod(Tyep1 t1, Type2 t2) { //1. call to Exi

这向我展示了如何模拟构造函数中包含参数的类。下面是关于的
Mock.的一个示例,但它没有显示如何使用函数语法模拟构造函数

public class MyClass
{
    public MyClass(IDependency1 dep1, IDependency2 dep2, IDependency3 dep3)
    {}

    public ReturnType MyNewMethod(Tyep1 t1, Type2 t2)
    {
       //1. call to ExistingMethod1();
       //2. call to ExistingMethod2();
       //3. call using the DbContext
       //4. call using the Logger
    }
}
我从第一篇博文中得到了类似的信息

var dep1 = new Mock<IDependency1>(); 
var dep2 = new Mock<IDependency2>();
var dep3 = new Mock<IDependency3>();

object[] arrParams = { dep1.Object, dep2.Object, dep3.Object }
var sut = new Mock<MyClass>(arrParams);

如果要测试
MyClass
,可能需要模拟依赖项:

// Arrange
var mockDep1 = new Mock<IDependency1>();
var mockDep2 = new Mock<IDependency2>();
var mockDep3 = new Mock<IDependency3>();

var myTestInstance = new MyClass(mockDep1.Object, mockDep2.Object, mockDep3.Object);

// Act
var result = myTestInstance.DoSomething();

// Assert
Assert.AreEqual(result, myExpectedResult); // check the direct result
mockDep1.Verify(mock => mock.SomeMethodOnMock(It.IsAny<string>()), Times.Once); // SomeMethodOnMock was called once
// ... etc
//排列
var mockDep1=new Mock();
var mockDep2=新的Mock();
var mockDep3=新的Mock();
var myTestInstance=new MyClass(mockDep1.Object、mockDep2.Object、mockDep3.Object);
//表演
var result=myTestInstance.DoSomething();
//断言
Assert.AreEqual(result,myExpectedResult);//检查直接结果
mockDep1.Verify(mock=>mock.SomeMethodOnMock(It.IsAny()),Times.Once);//有一次调用了SomeMethodOnMock
// ... 等
另一方面,如果
MyClass
是您想要为另一个测试对象模拟的依赖项,那么从中提取接口的最佳方法(例如
IMyClass
),这样您就可以以更干净的方式测试您的类


Moq允许您模拟非密封类,但如果在测试期间没有其他方法执行许多不相关的代码,并且您只能设置/验证非密封的虚拟或抽象成员,那么Moq模拟是一种故障安全的方法。

使用Moq模拟需要模拟类,使其具有虚拟方法,或者您可以模拟任何接口。当您使用moq进行模拟时,它将动态创建一个动态实现,因此它不依赖于您的实现。在你的情况下,你可以这样做

public class MyClass
{
    public MyClass(IDependency1 dep1, IDependency2 dep2, IDependency3 dep3)
    {}

    public ReturnType MyNewMethod(Tyep1 t1, Type2 t2)
    {
       //1. call to ExistingMethod1(); --> I'll just setup the return value
       //2. call to ExistingMethod2(); --> I'll just setup the return value
       //3. call using the DbContext   --> ???
       //4. call using the Logger      --> ???
    }
}

    Mock<MyClass> mockedObj = new Mock<MyClass>();

    mockedObj.SetUp(x=>x.MyNewMethod()).Returns(objectOfReturnType);
公共类MyClass
{
公共MyClass(IDependency1 dep1、IDependency2 dep2、IDependency3 dep3)
{}
公共返回类型MyNewMethod(类型1 t1,类型2 t2)
{
//1.调用ExistingMethod1();-->我将只设置返回值
//2.调用ExistingMethod2();-->我将只设置返回值
//3.使用DbContext-->?调用???
//4.使用记录器调用-->???
}
}
Mock mockedObj=新Mock();
SetUp(x=>x.MyNewMethod()).Returns(objectOfReturnType);
在这里,您需要使MyNewMethod成为虚拟的。return objectOfReturnType是作为测试对象创建的对象。因此,您的方法主体细节不是必需的。这就是模拟的思想,您正在用伪实现(本例中的设置)模拟您的实际实现。您可以改变不同的返回对象,这取决于您将如何测试被测试的类。我建议您首先阅读单元测试101

请注意,您正在设置MyNewMethod的行为方式。您的实现可能做了很多事情,但这里您关心的是它的回报。这就是为什么该方法也必须是虚拟的,它将被Moq覆盖并返回您刚刚设置的内容。在内部,这个方法可能会调用不同的东西…所以你不在乎


另外,你应该阅读Moq的基础,你可以在这里找到它

我不确定
Mock.of是否允许这样做,我必须重新检查。你可以使用linq版本作为依赖项,使用标准版本作为主题类为什么需要模拟构造函数?单元测试模拟的思想是将被测试的类与外部依赖项隔离开来。一旦您进行了模拟,在您的示例dep1、dep2、dep3中,您只需创建通过模拟的MyClass对象。不需要模拟构造函数看看这里的文档如果模拟的是没有默认构造函数的抽象类,或者是有虚拟方法要模拟的具体类,则需要提供构造函数参数。不过,我认为你不能用
Mock.Of
做到这一点。只要
新建Mock(args)
或者使用一个接口作为您的抽象机制就可以了。现在,我正试图解决两个问题。1) 我添加到此服务类的方法调用同一类中的其他方法。通过上面的代码,这个问题将得到解决。2) 我的方法还依赖于DbContext、Logger等。因此,如果我不将它们添加到构造函数中,我将如何控制它们的行为。这才是我真正的困惑。不,你只是嘲笑一个层次的依赖。否则,它就不再是单元测试了。如果您是依赖于MyClass的测试类2,那么您只需模拟MyClass,而不必担心它的依赖性。您可以根据您的输入设置方法,以确定它们应该返回什么。如果您共享您想要共享的类,我可以给您一些指导,如何模拟依赖项并设置这些依赖项的方法让我们假设我正在添加一个名为
MyNewMethod()
的方法,我正在测试该方法。此方法正在调用两个现有方法
ExistingMethod1()
ExistingMethod2()
。当我看你的代码时,我发现你没有模仿
MyClass
。当我测试新方法时,它将调用两个现有方法的
REAL
版本(尽管它们很复杂)。我认为他们应该被嘲笑。@Richard77:所以如果我理解得很好,你可以测试
MyClass
。在这种情况下,
MyClass
不应被模拟。如果在测试期间调用它的现有方法是可以的,因为它们属于被测试的类。但是,不希望调用
MyClass
的依赖项,因为它们不属于您的类,您只需测试第三方代码,至少部分测试。这就是Moq存在的原因。如果需要,您可以设置模拟依赖项的成员以返回一些伪代码,并且可以断言这些成员是否被调用。
public class MyClass
{
    public MyClass(IDependency1 dep1, IDependency2 dep2, IDependency3 dep3)
    {}

    public ReturnType MyNewMethod(Tyep1 t1, Type2 t2)
    {
       //1. call to ExistingMethod1(); --> I'll just setup the return value
       //2. call to ExistingMethod2(); --> I'll just setup the return value
       //3. call using the DbContext   --> ???
       //4. call using the Logger      --> ???
    }
}

    Mock<MyClass> mockedObj = new Mock<MyClass>();

    mockedObj.SetUp(x=>x.MyNewMethod()).Returns(objectOfReturnType);