我正在修改一个类方法,该方法格式化一些输入参数日期,并将其用作另一个程序集中基类的方法调用的参数。
我想要验证我传递给我的方法的日期在传递给基类方法时是否处于正确的格式,因此我希望使用Moq模拟基类方法调用。这是否可能?
我正在修改一个类方法,该方法格式化一些输入参数日期,并将其用作另一个程序集中基类的方法调用的参数。
我想要验证我传递给我的方法的日期在传递给基类方法时是否处于正确的格式,因此我希望使用Moq模拟基类方法调用。这是否可能?
截至2013年,使用最新版的Moq你可以这样做。这里有一个示例
。public class ViewModelBase
{
public virtual bool IsValid(DateTime date)
{
//some complex shared stuff here
}
}
public class MyViewModel : ViewModelBase
{
public void Save(DateTime date)
{
if (IsValid(date))
{
//do something here
}
}
}
public void MyTest()
{
//arrange
var mockMyViewModel = new Mock<MyViewModel>(){CallBase = true};
mockMyViewModel.Setup(x => x.IsValid(It.IsAny<DateTime>())).Returns(true);
//act
mockMyViewModel.Object.Save();
//assert
//do your assertions here
}
如果我理解你的问题正确,你有一个在其他程序集中定义的A类,然后实现了一个B类,大致像这样:
public class B : A
{
public override MyMethod(object input)
{
// Do something
base.MyMethod(input);
}
}
现在你想验证是否已经调用了base.MyMethod方法?
我不认为你可以通过动态模拟库来实现这一点,所有的动态模拟库(TypeMock除外)都是通过动态生成从相关类型派生的类来工作的。
在您的情况下,您无法要求 Moq 派生自 A,因为您想测试的是 B。
这意味着您必须请求 Moq 给您一个 Mock<B>
。但是,这意味着生成的类型派生自 B,虽然它可以重写 MyMethod (仍然是虚函数)并调用其基类(B.MyMethod),但它无法获取到原始类并验证 B 是否调用了base.MyMethod
。
想象一下,您需要编写一个从 B 派生的类(C)。虽然您可以重写 MyMethod,但无法验证 B 是否调用了 A:
public class C : B
{
public override MyMethod(object input)
{
// How to verify that base calls its base?
// base in this context means B, not A
}
}
除了 TypeMock 可能有一些例外,动态 mock 库不能做任何你不能手动完成的事情。
然而,我会假设调用您要验证的基本方法具有一些可观察的副作用,因此如果可能的话,可以使用基于状态的测试来验证调用该方法的结果,而不是行为测试。
无论如何,在大多数情况下,状态测试应该是您的默认方法。
将基类方法包装在一个方法和设置该方法中,例如:
public class B : A
{
public virtual BaseMyMethod(object input)
{
// Do something
base.MyMethod(input);
}
public override MyMethod(object input)
{
// Do something
BaseMyMethod(input);
}
}
现在设置BaseMyMethod
在it技术中很可能会出现模拟基类的情况。但您需要修改目标类。
例如,DerivedClass 继承自 BaseClass。 BaseClass 包含方法 MethodA(), MethodB(), MethodC()... 而DerivedClass则有这个方法:
void MyMethod() {
this.MethodA();
this.MethodB();
this.MethodC();
}
您想要模拟基类,以验证所有MethodA()、MethodB()和MethodC()是否在MyMethod()内被调用。
您需要在DerivedClass中创建一个字段:
class DerivedClass {
private BaseClass self = this;
...
}
你还需要修改MyMethod()方法:
void MyMethod() {
self.MethodA();
self.MethodB();
self.MethodC();
}
public void setMock(BaseClass mock) {
this.self = mock;
}
DerivedClass target = new DerivedClass ();
BaseClass mock = new Mock(typeof(BaseClass));
target.setMock(mock);
target.MyMethod();
mock.verify(MethodA);
mock.verify(MethodB);
mock.verify(MethodC);
var real = new SubCoreClass();
var mock = new Mock<SubCoreClass>();
mock.CallBase = true;
var obj = mock.Object;
mock
.Setup(c => c.Execute())
.Callback(() =>
{
obj.CallBaseMember(typeof(Action), real, "Execute");
Console.WriteLine(obj.GetHashCode());
}
);
public static Delegate CreateBaseCallDelegate(object injectedInstance, Type templateDelegate, object instanceOfBase, string methodName)
{
var deleg = Delegate.CreateDelegate(templateDelegate, instanceOfBase, methodName);
deleg.GetType().BaseType.BaseType.GetField("_target", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(deleg, injectedInstance);
return deleg;
}
public static object CallBaseMember(this object injectedInstance, Type templateDelegate, object instanceOfBase, string methodName, params object[] arguments)
{
return CreateBaseCallDelegate(injectedInstance, templateDelegate, instanceOfBase, methodName).DynamicInvoke(arguments);
}
var mockMyViewModel = new Mock<MyViewModel>(new Mock<IMyViewModelConstructorArg>().Object){CallBase = true};
]。 - brenthompson2