如何设置Moq来执行Moq的某些方法

时间:2012-09-27 12:13:41

标签: moq

我有一个测试,我传入一个像这样的对象:

var repo = new ActualRepo();

var sut = new Sut(repo);

在我的测试中,Repo有一个我需要实际执行的方法,而另一个我想模拟而不执行的方法。

例如,请使用此伪代码:

var repo = new Mock<IRepo>();

repo.Setup(m => m.MethodIWantToCall()).WillBeExecuted();
repo.Setup(m => m.MethodIWantToMock()).Returns(false);

使用Moq,这是可能的,怎么做?

编辑: 我过去使用过TypeMock,你可以做类似的事情。

Isolator.When(() => repo.MethodToIgnore()).WillBeIgnored();
Isolator.When(() => repo.MethodToActuallyRun()).WillBeExecuted();

2 个答案:

答案 0 :(得分:4)

问题不是很确定这是否有用但如果您要模拟的方法是虚拟,则可以部分模拟对象。

public class Foo {
    public string GetLive() {
        return "Hello";
    }

    public virtual string GetMock() {
        return "Hello";
    }
}

public class Snafu {
    private Foo _foo;
    public Snafu(Foo foo) {
      _foo = foo;
    }

    public string GetMessage() {
        return string.Format("{0} {1}", _foo.GetLive(), _foo.GetMock());
    }
}


[TestMethod]
public void NotMocked() {
    var snafu = new Snafu(new Foo());
    Assert.AreEqual("Hello Hello", snafu.GetMessage());
}


[TestMethod]
public void Mocked() {

    var mockFoo = new Mock<Foo>();
    mockFoo.Setup(mk => mk.GetMock()).Returns("World");

    var snafu = new Snafu(mockFoo.Object);

    Assert.AreEqual("Hello World", snafu.GetMessage());
}

答案 1 :(得分:3)

如果使用相同的对象,除非其中一个方法是虚拟的并且您将模拟基于类型而不是接口,否则无法使用Moq执行此操作。

那是因为当您基于接口传递模拟对象时,您没有传递真实对象,因此它无法访问对象的实际方法。

您正在传递dynamic proxy,它将响应已设置响应的方法。

我相信TypeMock会在运行时重写程序集来实现这一点,Moq肯定不会这样做。

如果你想用Moq获得类似的结果:

  • 您可以模拟这两种方法
  • 您必须将两种方法都提取到不同的依赖项,以便模拟一个依赖项而不是另一个依赖项。
  • 你可以让你需要模拟的方法是虚拟的,这将是我更喜欢的解决方案。

编辑:我在阅读AlanT's answer后编辑了我的答案是否正确。