3

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

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);

使用最小起订量,这可能吗?怎么做?

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

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

2 回答 2

5

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

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());
}
于 2012-09-27T15:26:40.087 回答
3

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

这是因为当你传递一个基于接口的模拟对象时,你并没有传递一个真实的对象,因此它无法访问该对象的真实方法。

您正在传递一个动态代理,它将响应它已设置响应的方法。

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

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

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

编辑:阅读AlanT 的答案后,我编辑了我的答案以确保正确性。

于 2012-09-27T12:46:12.447 回答