我有以下方法:
public CustomObect MyMethod()
{
var lUser = GetCurrentUser();
if (lUser.HaveAccess)
{
//One behavior
}
else
{
//Other behavior
}
//return CustomObject
}
我想模仿IMyInterface.GetCurrentUser
,以便在调用MyMethod
时我可以到其中一个代码路径进行检查。如何用Moq做到这一点?
我正在做以下事情:
var moq = new Mock<IMyInterface>();
moq.Setup(x => x.GetCurrentUser()).Returns(lUnauthorizedUser);
//act
var lResult = moq.Object.MyMethod();
但由于某种原因,lResult
始终为null
,当我在调试中尝试进入MyMethod
时,我总是跳到下一个语句。
答案 0 :(得分:111)
这称为部分模拟,我知道在moq中执行它的方式需要模拟类而不是接口,然后将模拟对象上的“Callbase”属性设置为“true”。
这将要求您正在测试虚拟类的所有方法和属性。假设这不是问题,那么您可以编写如下测试:
var mock = new Mock<YourTestClass>();
mock.CallBase = true;
mock.Setup(x => x.GetCurrentUser()).Returns(lUnauthorizedUser);
mockedTest.Object.MyMethod();
答案 1 :(得分:22)
扩展lee's answer,
您不需要在您的班级上创建虚拟的所有方法和属性,只需要您想要模拟的方法和属性。
另外,应该注意的是,你应该嘲笑你班级的具体实施。
var mock = new Mock<YourTestClass>(); // vs. var mock = new Mock<IYourTestInterface>();
如果您的类没有默认构造函数,您还需要指定通过以下方式传递给它的参数:
var mock = new Mock<YourTestClass>(x, y, z);
// or
var mock = new Mock<YourTestClass>(MockBehavior.Default, x, y, z);
其中x, y, z
分别是构造函数的第一,第二和第三个参数。
最后,如果您要模拟的方法受到保护,则需要包含Moq.Protected
using Moq.Protected;
TReturnType returnValue = default(TReturnType);
mock.Protected()
.Setup<TReturnType>("YourMockMethodName", It.IsAny<int>()) // methodname followed by arguments
.Returns(returnValue);
答案 2 :(得分:16)
我遇到了类似的情况。我发现以下代码使我可以更灵活地使用模拟方法和接口的某些特定实现中的实际方法:
var mock = new Mock<ITestClass>(); // Create Mock of interface
// Create instance of ITestClass implementation you want to use
var inst = new ActualTestClass();
// Setup to call method of an actual instance
// if method returns void use mock.Setup(...).Callback(...)
mock.Setup(m => m.SomeMethod(It.IsAny<int>())
.Returns((int x) => inst.SomeMethod(x));
现在您可以使用实际方法,但也可以使用Verify
之类的内容来查看它被调用的次数。
答案 3 :(得分:0)
由于这是搜索时的最佳结果,因此扩展了 lee 的答案,您可以通过使用 As<T>()
方法分配接口来避免使用虚拟方法。
var mock = new Mock<YourTestClass>().As<IYourTestClass>();
mock.CallBase = true;
var realResult = mock.Object.YourMethod();
mock.Setup(c => c.YourMethod()).Returns("FAKE");
var fakeResult = mock.Object.YourMethod();
但是请注意,如果您的类在内部使用您以这种方式模拟的方法,它仍然会调用真正的方法,因为它不知道模拟的类型并且是从 this
调用的。这会降低这种方法的可用性,并且可能会让您(就像我一样)理解为什么关于这种模式的文档很少。