Moq假一种方法但使用另一种方法的真实实现

Sam*_*ach 39 .net c# nunit unit-testing moq

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

我想测试当Method1()抛出一个Exception,Method2()被调用并返回一个给定的值.

(投掷Method2()时被称为Method1()).

因此我需要Method2()用假的测试真实Method1(),它们是相同界面的方法.

这是我的测试代码:

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

我的目标是断言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>()));
Run Code Online (Sandbox Code Playgroud)

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

我已经单独测试了IService,但我现在希望测试它与它的交互MBase.

Sun*_*nov 61

你可以这样做:

var mock = new Mock<MyNetworkStream>(){ CallBase = true };
mock.Setup(m => m.Method1....
Run Code Online (Sandbox Code Playgroud)

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

CallBase=true 通常用于测试抽象类(如果这是对或错,则超出了本问题的范围).

  • 如果类'MyNetworkStream`通过一个公共方法实现`Method1`,它不具有`virtual`(或`abstract`或`override`)修饰符,你还可以在`Mock <MyNetworkStream上设置这个`Method1`吗? >`? (4认同)
  • @JeppeStigNielsen,不,我认为你不能。在我的例子中,我的两个方法都来自一个抽象类。 (2认同)

Chr*_*sal 8

在这种情况下(除非还有更多内容)我将创建自己的测试类,使用真实行为扩展类,实现您需要模拟的接口.这样,您可以模拟一个值,并回退到实际功能的基类.