2009-08-18 107 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 
}