C# Moq 伪造一种方法,但使用另一种方法的真实实现

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19054563/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 13:59:43  来源:igfitidea点击:

Moq fake one method but use real implementation of another

c#.netunit-testingnunitmoq

提问by Sam Leach

Given an interface IServicethat has Method1()and Method2().

给定一个IService具有Method1()和的接口Method2()

I want to test that when Method1()throws an Exception, Method2() is called and returns a given value.

我想测试当Method1()throws an Exception, Method2() 被调用并返回给定值时

(Method2()is called when Method1()throws).

(抛出Method2()时调用Method1())。

Therefore I need to test a real Method2()with a fake Method1(), they are methods of the same interface.

因此我需要Method2()用 fake测试 real Method1(),它们是相同接口的方法。

Here is my test code:

这是我的测试代码:

MBase sut.MethodX()is the only entry point. It uses IService.

MBase sut.MethodX()是唯一的切入点。它使用IService.

My aim is to assert that Method2()returns something.

我的目标是断言会Method2()返回一些东西

// Arrange
// Fake bytes in.
var networkStreamMock = new Mock<INetworkStream>();
networkStreamMock.Method1(x => x.Read(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<int>())).Returns(It.IsAny<byte[]>());

// Force throw TimeoutException.
var mock = new Mock<IService>();
mock.Setup(x => x.Method1(new Message
{ 
    Xml = Xml,  
}
)).Throws<TimeoutException>();

// Check Method 2 is called. (this is done in its own test so commented out)
// mock.Setup(m => m.Method2(It.IsAny<Message>())).Verifiable();

// New MBase.
IKernel kernel = new StandardKernel(new FakeBindings());
kernel.Rebind<IService>().ToConstant(mock.Object);
MBase sut = kernel.Get<M>();

// Act
sut.MethodX(networkStreamMock.Object);

// Here I would like to assert on the return value of Method2
mock.Verify(m => m.Method2(It.IsAny<Message>()));

Is this possible with Moq or another mocking framework? How do I do it? I can create a manual mock with a fake implementation of Method1()and a real implementation of Method2()but I wonder if there is a better approach.

这可以通过 Moq 或其他模拟框架实现吗?我该怎么做?我可以创建一个带有假实现Method1()和真实实现的手动模拟,Method2()但我想知道是否有更好的方法。

I have already tested IServicein isolation but I now wish to test it's interaction with MBase.

我已经单独测试过IService,但我现在希望测试它与MBase.

采纳答案by Sunny Milenov

You can do this with:

你可以这样做:

var mock = new Mock<MyNetworkStream>(){ CallBase = true };
mock.Setup(m => m.Method1....

The above code will use the real implementation of MyNetworkStream for any method/property which is not explicitly setup. I.e. it'll call the real Method2(), while the Method1() will be the mocked version.

上面的代码将对任何未明确设置的方法/属性使用 MyNetworkStream 的真实实现。即它将调用真正的 Method2(),而 Method1() 将是模拟版本。

CallBase=trueis usually meant to test abstract classes (if this is right or wrong, is out of the scope of this question).

CallBase=true通常是为了测试抽象类(如果这是对的还是错的,超出了这个问题的范围)。

回答by Chris Missal

In this case (unless there's a lot more going on) I would just create my own test class extending the class with the real behavior, that implements the interface you need to mock. This way you can mock the one value, and fallback to the base class for the real functionality.

在这种情况下(除非有更多事情发生),我将创建自己的测试类,使用真实行为扩展类,实现您需要模拟的接口。通过这种方式,您可以模拟一个值,并回退到真正功能的基类。