模拟对象中的方法是否有效?
例如,如果我有一个方法名为Method1
的对象,并且我模拟了该对象:
var mockobject= Mock<myobject>();
下一次调用方法是否有效:
mockobject.Method1()
这是一个澄清模拟对象的问题。
答案 0 :(得分:1)
如果您正在使用方法实现来模拟具体类或抽象类。对于虚拟方法,您有两种选择。
创建Setup
以伪造方法调用
mockobject.Setup(x => x.Method1()).Returns(true);
在模拟上设置CallBase = true
以调用Method1
方法的具体行为。
mockobject.CallBase = true;
用法:
public class MyClass
{
public virtual int MyMethod()
{
return 5;
}
}
[Test]
public void ShouldGiveMeZero()
{
var mockMyClass = new Mock<MyClass>();
// returns default(int)
Assert.AreEqual(0, mockMyClass.Object.MyMethod());
}
[Test]
public void ShouldGiveMeFive()
{
var mockMyClass = new Mock<MyClass>();
mockMyClass.CallBase = true;
// calls concrete implementation
Assert.AreEqual(5, mockMyClass.Object.MyMethod());
}
[Test]
public void ShouldGiveMeSix()
{
var mockMyClass = new Mock<MyClass>();
mockMyClass.Setup(x => x.MyMethod()).Returns(6);
// calls Setup
Assert.AreEqual(6, mockMyClass.Object.MyMethod());
}
答案 1 :(得分:1)
首先,请注意您的示例将从不编译:
mockobject.Method1()
Method1
并不存在于模拟对象本身 - 它存在于底层的模拟对象实例中:
mockobject.Object.Method1();
该通话的行为取决于您MockBehavior
使用的Strict
(Loose
或virtual
)。这还取决于您调用的方法是否标记为Method1
。
如果MyObject
是非虚拟的,将使用实际类型的实现,因为Mock不能模拟非虚方法。
例如,如果public class MyObject
{
public int Method1()
{
return 1;
}
}
定义如下:
mockObject.Object.Method1()
1
将返回Method1
,因为Mock无法为该方法提供任何其他实现。
现在,如果virtual
被声明为public virtual int Method1()
{
return 1;
}
:
MockBehavior
MockBehavior.Loose
开始发挥作用。默认值为.Setup
,这意味着未使用default(T)
方法定义的方法将返回T
,其中var mockObject = new Mock<MyObject>(MockBehavior.Default);
int result = mockObject.Object.Method1();
是方法的返回类型。以下是:
0
除非您使用.Setup
使其返回,否则将始终返回CallBase = true
。您还可以在Mock<MyObject>
实例上指定.Setup
,并且将针对未使用MockBehavior.Strict
定义的方法调用基础实现。
如果你正在使用var mockObject = new Mock<MyObject>(MockBehavior.Strict);
int result = mockObject.Object.Method1(); // Always throws an exception
,未实现的方法将抛出异常:
{{1}}
答案 2 :(得分:0)
如果您查看quickstart guide,可以使用简单的示例,例如
var mock = new Mock<IFoo>();
mock.Setup(foo => foo.DoSomething("ping")).Returns(true);
请注意调用Setup
以使mock / fake实际执行某些操作。
答案 3 :(得分:0)
在这种情况下,您已为Method1创建了默认存根。如果您要手动创建它,则代码类似于:
public class MyObject {
public virtual void Method1() {
throw new NotImplementedException();
}
}
你的存根将是:
public class Stub : MyObject {
public override void Method1() {
}
}
所以现在不是获取NotImplementedException,而是拥有一个MyObject实例,它允许您调用Method1而不管其原始实现。
请注意我对虚拟的使用。如果不使用虚拟,Moq就无法覆盖。
这实际上是我最喜欢的嘲笑用法之一。很多人为了嘲笑而滔滔不绝地使用界面#34;大多数基线方案只需要方法是虚拟的。一般来说,我几乎将我创建的每个公共方法标记为虚拟。如果公共方法不能是虚拟方法,则可能违反了开放封闭原则。