2009-08-18 53 views
18

我modifiying哪些格式paramater其随后在一个方法调用到基类(其居住在另一个组件)用作PARAMS日期一些输入一个类方法的基类的方法调用。惩戒与起订量

我想验证我通过我的方法日期是正确的格式,当他们被传递给基类的方法,所以我想MOQ基类的方法调用。 Moq有可能吗?

回答

12

如果我正确理解你的问题,你有一些其他组件中定义的类A,然后在B类实现或多或少是这样的:

public class B : A 
{ 
    public override MyMethod(object input) 
    { 
     // Do something 
     base.MyMethod(input); 
    } 
} 

现在你要验证的基础。 MyMethod被调用?

我不明白你如何用动态模拟库做到这一点。所有动态模拟库(具有TypeMock的豁免)通过动态发布从所讨论类型派生的类来工作。

在你的情况,你不能很好地询问起订量从一个推导,因为你想测试

这意味着,你必须问起订量给你一个Mock<B>。但是,这意味着发出的类型来自B,并且虽然它可以重写MyMethod(它仍然是虚拟的)并调用它的基础(B.MyMethod),但它无法到达原始类并验证B调用base.MyMethod

想象一下,你必须写一个类(C),从B派生虽然你可以重写的MyMethod,有没有办法可以验证B调用答:

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,动态模拟库不能做你不能做的手工。

但是,我会假设调用您正在尝试验证的基本方法有一些可观察到的副作用,所以如果可能,您可以使用基于状态的测试而不是基于行为的测试来验证调用方法的结果?

无论如何,在大多数情况下,基于状态的测试应该是您的默认方法。

1

同意马克,这是不可能使用Moq。

根据您的情况,你可以考虑swithcing from inheritance to composition。然后你将能够嘲笑依赖并验证你的方法。当然,在某些情况下,它可能不值得。

1

在包裹的方法和设置该方法 例如基类方法

public class B : A 
{ 
    public virtual BaseMyMethod(object input) 
    { 
     // Do something 
     base.MyMethod(input); 
    }  
public override MyMethod(object input) 
    { 
     // Do something 
     BaseMyMethod(input); 
    } 
} 

,现在安装的BaseMyMethod

0

我发现这个解决方案 - 丑陋,但它可以工作。

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); 
} 
3

这是很可能的嘲笑基类。但是你将不得不修改目标课。

例如,DerivedClass延伸BaseClassBaseClass的有方法治法()方法b()MethodC() ... 的DerivedClass有这个方法:

void MyMethod() { 
    this.MethodA(); 
    this.MethodB(); 
    this.MethodC(); 
} 

你想模拟基类,以验证所有治法()方法b()MethodC()被称为内的MyMethod()

你必须在DerivedClass创建一个字段:

class DerivedClass { 
    private BaseClass self = this; 
    ... 
} 

,你也必须修改的MyMethod()

void MyMethod() { 
    self.MethodA(); 
    self.MethodB(); 
    self.MethodC(); 
} 

还添加了一个方法,它可以使用Mock对象注入this.self字段

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

使用此TECHNIC,你也可以模拟嵌套的方法调用。

+0

编译器错误:关键字'this'在当前上下文中不可用。在派生类字段中。 – 2018-02-05 22:37:04

7

截至2013年与最新的Moq你可以。这是一个example

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 
}