如何设置Moq以执行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();

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

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

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

这是因为当你传递一个基于接口的模拟对象时,你没有传递一个真实的对象,所以它不能访问对象的真实方法。

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

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

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

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

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

最新更新