模拟对象中的方法是否有效?

时间:2014-10-21 14:36:25

标签: c# mocking moq

模拟对象中的方法是否有效? 例如,如果我有一个方法名为Method1的对象,并且我模拟了该对象:

var mockobject= Mock<myobject>();

下一次调用方法是否有效:

mockobject.Method1()

这是一个澄清模拟对象的问题。

4 个答案:

答案 0 :(得分:1)

如果您正在使用方法实现来模拟具体类或抽象类。对于虚拟方法,您有两种选择。

  1. 创建Setup以伪造方法调用

    mockobject.Setup(x => x.Method1()).Returns(true);

  2. 在模拟上设置CallBase = true以调用Method1方法的具体行为。

    mockobject.CallBase = true;

  3. 用法:

    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使用的StrictLoosevirtual)。这还取决于您调用的方法是否标记为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;大多数基线方案只需要方法是虚拟的。一般来说,我几乎将我创建的每个公共方法标记为虚拟。如果公共方法不能是虚拟方法,则可能违反了开放封闭原则。