2011-07-26 50 views
6

這就是情況。我有異步調用,所以我需要爲此做Mid級以便能夠測試它。使用Moq定義模擬對象的實現方法

request.BeginGetResponse(new AsyncCallback(LoginCallback), requestState); 

因此,爲了能夠測試這個沒有真正的請求,我創造了我可以模擬的接口。

public interface IRequestSender 
    { 
     void Send(HttpWebRequest request, AsyncCallback internalCallback, object requestState); 
    } 

然後在執行我可以使用電話一樣,一個在上面,我可以提供一些模擬類調用我的回調方法不論是何種請求是否有效。我的模擬課程看起來像這樣。

public class RequestSenderMock : IRequestSender 
    { 
     public void Send(HttpWebRequest request, AsyncCallback internalCallback, object requestState) 
     { 
      var result = new Mock<IAsyncResult>(); 
      result.Setup(x => x.AsyncState).Returns(requestState); 
      internalCallback(result.Object); 
     } 
    } 

我現在可以在我的單元測試中輕鬆創建模擬對象並使用它。但是,當我創建

var sender = new Mock<RequestSenderMock>(); 

我無法驗證此對象的調用計數。

sender.Verify(x => x.Send(It.IsAny<HttpWebRequest>(), It.IsAny<AsyncCallback>(), It.IsAny<object>()), Times.Once()); 

它說我的方法需要是虛擬的。 有沒有辦法做到這一點,而不使我的方法虛擬?如果我能夠在使用接口時以某種方式指定方法推進,那將是最好的。

var sender = new Mock<IRequestSender>(); 

而且,以某種方式用Setup方法或其他一些方法來實現這個模擬對象。比我會簡單地刪除我的模擬類。 這可能嗎?你有什麼建議?

回答

8

我覺得很困惑,你正在創建一個手動模擬,並使用一個模擬框架來模擬它(嘲笑一個模擬)。我會考慮將您的自定義函數轉換爲一些實用程序類,並使用回調代替。

例子:

public class RequestSenderHelpers 
{ 
    public static void Send(HttpWebRequest request, AsyncCallback internalCallback, object requestState) 
    { 
     var result = new Mock<IAsyncResult>(); 
     result.Setup(x => x.AsyncState).Returns(requestState); 
     internalCallback(result.Object); 
    } 

} 

    [Test] 
    public void Callback_VerifyingWithMethodImplementation_VerifyWorks() 
    { 
     // arrange 
     var sender = new Mock<IRequestSender>(); 
     sender.Setup(s => s.Send(It.IsAny<HttpWebRequest>(), It.IsAny<AsyncCallback>(), It.IsAny<object>())).Callback<HttpWebRequest, AsyncCallback, object>(RequestSenderHelpers.Send); 

     // act 
     sender.Object.Send(null, delegate {}, null); 

     // assert 
     sender.Verify(s => s.Send(It.IsAny<HttpWebRequest>(), It.IsAny<AsyncCallback>(), It.IsAny<object>())); 
    } 

爲了避免冗長的設置,你可以包裝方法的設置中的擴展方法,並相應地改變你的測試:

public static class RequestSenderHelpers 
{ 
    public static void Send(HttpWebRequest request, AsyncCallback internalCallback, object requestState) 
    { 
     var result = new Mock<IAsyncResult>(); 
     result.Setup(x => x.AsyncState).Returns(requestState); 
     internalCallback(result.Object); 
    } 

    public static void SetupSendWithMockedAsyncResult(this Mock<IRequestSender> sender) 
    { 
     sender.Setup(s => s.Send(It.IsAny<HttpWebRequest>(), It.IsAny<AsyncCallback>(), It.IsAny<object>())).Callback<HttpWebRequest, AsyncCallback, object>(Send);    
    } 

} 

    [Test] 
    public void Callback_VerifyingWithMethodImplementation_VerifyWorks() 
    { 
     // arrange 
     var sender = new Mock<IRequestSender>(); 
     sender.SetupSendWithMockedAsyncResult(); 

     // act 
     sender.Object.Send(null, delegate {}, null); 

     // assert 
     sender.Verify(s => s.Send(It.IsAny<HttpWebRequest>(), It.IsAny<AsyncCallback>(), It.IsAny<object>())); 
    } 
+0

謝謝,這正是我需要的。 :) – Vajda

相關問題