![](/img/trans.png)
[英]How to mock a class without default constructor using Mock.Of<T>()?
[英]How to mock a class that has parameters in the constructor using Mock.Of<> syntax?
这个问题向我展示了如何在构造函数中模拟一个具有参数的类。 这是Mock.Of<>
上的一个很好的块帖子 ,但它没有显示如何使用函数语法模拟构造函数。
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);
那么如何使用Mock.Of<>
语法模拟构造函数中具有参数的类?
新方法不仅会调用现有方法 ,还会访问DbContext
, logger
以及其他可能的服务。 所以,除了我正在测试的方法之外,我需要模拟一切。
public class MyClass
{
public MyClass(MyDbContext context, ISecurityService secService, ILogger logger)
{}
public ReturnType1 ExistingMethod1(Type1 t1){}
public ReturnType2 ExistingMethod2(Type t){}
public MyEntity 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 --> ???
var x = ExistingMethod1(t1); //1.
var y = ExistingMethod1(x); //2.
var result context.MyEntities. //3.
.Where(e => e.id == y.MyEntityId)
.ToList();
return result;
}
}
使用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);
在这里你需要使MyNewMethod虚拟化。 返回objectOfReturnType是您作为测试对象创建的对象。 所以不需要或不需要您的方法主体细节。 这就是模拟的想法,你用虚假实现模拟你的实际实现(在这种情况下是设置)。 您可以根据测试类的测试方式来改变不同的返回对象。 我建议你先阅读单元测试101。
请注意,您正在设置MyNewMethod的行为方式。 你的实现可能会做很多事情,但在这里你关心的是它的回报。 这就是为什么该方法也必须是虚拟的,它将由Moq覆盖并返回您刚刚设置的内容。 在内部,该方法可能会调用不同的东西......所以你不在乎
另外你应该阅读Moq的基础知识,你可以在这里找到它https://github.com/Moq/moq4/wiki/Quickstart
如果要测试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
另一方面,如果MyClass
是您想要为另一个测试对象进行模拟的依赖项 ,那么从中提取接口的最佳方式(例如, IMyClass
)就可以以更清晰的方式测试您的类。
Moq允许您模拟非密封类,但如果没有其他方法可以在测试期间执行许多不相关的代码并且您可以仅设置/验证非密封的虚拟或抽象成员,则它更安全。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.