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

问题描述 投票:0回答:3

给定一个具有

IService
Method1()
的界面
Method2()

我想测试当

Method1()
抛出
Exception
时,调用
Method2(
) 并返回给定值

(当

Method2()

 抛出时调用 
Method1()
)。

因此我需要用假

Method2()

来测试真实的
Method1()
,它们是同一接口的方法。

这是我的测试代码:

MBase sut.MethodX()

是唯一的入口点。它使用 
IService

我的目标是断言

Method2()

 返回 
something

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

这可以通过 Moq 或其他模拟框架实现吗?我该怎么做? 我可以创建一个手动模拟,其中包含

Method1()

 的假实现和 
Method2()
 的真实实现,但我想知道是否有更好的方法。

我已经单独测试了

IService

,但我现在希望测试它与 
MBase
 的交互。

c# .net unit-testing nunit moq
3个回答
82
投票
您可以通过以下方式执行此操作:

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

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

CallBase=true

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


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


0
投票
为了能够模拟方法并使用类的其余部分作为真正的实现,您必须像这样创建模拟:

var myServiceMock = new Mock<MyService>(){ CallBase = true }.As<IMyService>();
然后你就可以设置它,而不必使用虚拟方法或类似的技巧修改主类。

© www.soinside.com 2019 - 2024. All rights reserved.