使用 Moq 确定是不是调用了方法
Posted
技术标签:
【中文标题】使用 Moq 确定是不是调用了方法【英文标题】:Using Moq to determine if a method is called使用 Moq 确定是否调用了方法 【发布时间】:2010-09-25 18:11:20 【问题描述】:据我了解,如果我调用更高级别的方法,我可以测试是否会发生方法调用,即:
public abstract class SomeClass()
public void SomeMehod()
SomeOtherMethod();
internal abstract void SomeOtherMethod();
我想测试如果我调用SomeMethod()
,那么我希望SomeOtherMethod()
会被调用。
我认为这种测试可以在模拟框架中使用是否正确?
【问题讨论】:
【参考方案1】:您可以通过使用验证来查看您已模拟的事物中的方法是否已被调用,例如:
static void Main(string[] args)
Mock<ITest> mock = new Mock<ITest>();
ClassBeingTested testedClass = new ClassBeingTested();
testedClass.WorkMethod(mock.Object);
mock.Verify(m => m.MethodToCheckIfCalled());
class ClassBeingTested
public void WorkMethod(ITest test)
//test.MethodToCheckIfCalled();
public interface ITest
void MethodToCheckIfCalled();
如果该行被留下注释,它会在您调用验证时抛出 MockException。如果未注释,它将通过。
【讨论】:
这是正确答案。然而,你必须明白一些事情。您不能模拟非抽象或虚拟的方法/属性(显然,所有接口方法和属性都可以模拟)。 -1: .Expect(...).Verifiable() 在此代码中是多余的。使用 AAA,您的验证是正确的。 .Verifiable 与 .Verify() 一起使用,即无 arg 版本。见***.com/questions/980554/… @I-- 可以【参考方案2】:不,模拟测试假定您使用某些可测试的设计模式,其中之一是注入。在您的情况下,您将测试 SomeClass.SomeMethod
和 SomeOtherMethod
必须在另一个需要接口的实体中实现。
您的Someclass
构造函数看起来像New(ISomeOtherClass)
。然后,您将模拟 ISomeOtherClass
并在其 SomeOtherMethod
上设置预期以被调用并验证预期。
【讨论】:
【参考方案3】:尽管我同意@Paul's answer 是推荐的方式,但我只想添加一种由moq
提供的替代方式。
由于SomeClass
是abstract
,它确实是可模拟的,但public void SomeMehod()
不是。关键是要找到模拟方法并以某种方式调用该方法,然后使用CallBase
将调用传播到SomeOtherMethod()
。这听起来像是一种 hack,但本质上很简单。如果建议的重构是不可能的,则可以使用它。
// This class is used only for test and purpose is make SomeMethod mockable
public abstract class DummyClass : SomeClass
public virtual void DummyMethod() => base.SomeMethod();
然后您可以设置DummyMethod()
通过设置CallBase
标志来传播调用。
//Arrange
var mock = new Mock<DummyClass>();
mock.Setup(m => m.DummyMethod()).CallBase();
//Act
mock.Object.SomeMethod();
//Assert
mock.Verify(m => m.SomeOtherMethod(), Times.Once);
【讨论】:
投反对票,因为它更复杂并且需要样板 DummyClass 赞成,因为有时您无法重构,您需要按原样测试实现以上是关于使用 Moq 确定是不是调用了方法的主要内容,如果未能解决你的问题,请参考以下文章