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
}
让我知道你的想法!
答案 0 :(得分:0)
模拟上还有CallBase
属性。据我所知,它应该与CallBase()方法做同样的事情,只是全局的模拟,但除了使用Setup()
或类似的东西显式模拟的方法。 / p>
这也许不是最好的解决方案,但您可以使用.CallBase=true;
设置模拟,然后对要模拟的所有内容使用显式Setup()
方法调用来恢复默认的模拟行为。
答案 1 :(得分:0)
不幸的是,截至目前,Moq
没有针对非返回类型方法的Callbase逻辑。
我建议:
Component
的新类,该类暴露类似以下内容 public void DoInternal(){ base.Do(); }
然后在你的回电中,你可以打电话给它。