C#Moq - 模拟void函数时CallBase的替代品

时间:2017-03-22 20:40:35

标签: c# .net unit-testing mocking moq

CallBase是Moq (C#单元测试库)中的一个函数,它允许使用自定义代码轻松挂钩到函数调用,同时还保留基函数调用。它的用途和限制在this SO post answer上注明。

该帖子提到的主要限制是CallBase函数未针对void函数实现

例如,假设我们想要模拟这个Component类:

public class Component
{
    public virtual void Do() { /* code */ }
}

然后我想用mock来调用base并运行自定义代码......

var mock = new Mock<Component>();
mock.Setup(m => m.Do())
    // preserve base call (NOT AN OPTION SINCE VOID FUNCTION!)
    .CallBase()
    .Callback(() => {/* custom test code */});

// if Do() was not a void function, this would be supported by the library

一个令人不满意的选择是通过将void函数拆分为两个来更改我们正在测试的实际代码结构:

public class Component
{
    public virtual void Do() { 
        this.DoInternal();
    }

    internal void DoInternal(){ /* code */ }
}

然后......

var mock = new Mock<Component>();
mock.Setup(m => m.Do())
    .Callback(() => 
    {
        // my custom code...

        // then call base
        mock.Object.DoInternal();
    });

这并不理想,因为它需要纯粹为了可测试性目的而修改实际的代码设计/结构,并且比Moq本身支持CallBase所需的工作/代码更多。这种解决方案有替代方案吗?也许实现一个扩展来支持库外的这个:

public static ICallbackResult<TMock> CallBase<TMock>(this ISetup<TMock> @this)
{
    // not implemented - seems difficult given how little Moq 
    // exposes the underlying implementations which it overrides

    // not sure about ICallbackResult<TMock> being what we'd want for return type...
    // the return type of the actual CallBase function is IReturnsResult<TMock>, but
    // that does not make much sense for a void function
}

让我知道你的想法!

2 个答案:

答案 0 :(得分:0)

模拟上还有CallBase属性。据我所知,它应该与CallBase()方法做同样的事情,只是全局的模拟,但除了使用Setup()或类似的东西显式模拟的方法。 / p>

这也许不是最好的解决方案,但您可以使用.CallBase=true;设置模拟,然后对要模拟的所有内容使用显式Setup()方法调用来恢复默认的模拟行为。

答案 1 :(得分:0)

不幸的是,截至目前,Moq没有针对非返回类型方法的Callbase逻辑。

我建议:

  1. 在GitHub上提出一个问题并对此答案发表评论,我会试着看看它+实现
  2. 与此同时,我建议不要编辑您的普通代码,并在测试类中创建一个继承自Component的新类,该类暴露类似以下内容
  3. public void DoInternal(){ base.Do(); }

    然后在你的回电中,你可以打电话给它。