2009-07-03 30 views
13

我在編寫一些單元測試來測試我創建的自定義ModelBinder時遇到了一些困難。我想單元測試的ModelBinder是我發佈的JsonDictionaryModelBinder here如何使用Moq測試自定義ModelBinder?

我遇到的問題是使用Moq模擬所有設置。由於HttpContextBase未被正確模擬,我一直收到空異常。我認爲。

有人可以幫我弄清楚我沒有做的事嗎?

這裏的單元測試我想寫的樣本不工作:

[TestMethod()] 
public void BindModelTest() 
{ 
    JsonDictionaryModelBinder target = new JsonDictionaryModelBinder(); 

    NameValueCollection nameValueCollection = new NameValueCollection() { 
     {"First", "1"}, 
     {"Second", "2"}, 
     {"Name", "Chris"}, 
     {"jsonValues", "{id: 200, name: 'Chris'}"} 
    }; 

    HttpContextBase httpContext = MockHelper.FakeHttpContext(HttpVerbs.Post, nameValueCollection); 

    ControllerContext controllerContext = 
     new ControllerContext(new RequestContext(httpContext, new RouteData()), new Mock<Controller>().Object); 


    Predicate<string> predicate = propertyName => (propertyName == "jsonValues"); 
    ModelBindingContext bindingContext = new ModelBindingContext() 
    { 
     Model = null, 
     ModelType = typeof(JsonDictionary), 
     ModelState = new ModelStateDictionary(), 
     PropertyFilter = predicate, 
     ValueProvider = new Dictionary<string, ValueProviderResult>() { { "foo", null } } 
    }; 

    //object expected = null; // TODO: Initialize to an appropriate value 
    var actual = target.BindModel(controllerContext, bindingContext) as JsonDictionary; 

    Assert.IsNotNull(actual); 

    Assert.AreEqual("Chris", actual["name"]); 
    //Assert.AreEqual(expected, actual); 
    Assert.Inconclusive("Verify the correctness of this test method."); 
} 

下面是上面所用的「FakeHttpContext」的方法:

public static class MockHelper 
{ 
    public static HttpContextBase FakeHttpContext(HttpVerbs verbs, NameValueCollection nameValueCollection) 
    { 
     var httpContext = new Mock<HttpContextBase>(); 

     var request = new Mock<HttpRequestBase>(); 
     request.Setup(c => c.Form).Returns(nameValueCollection); 
     request.Setup(c => c.QueryString).Returns(nameValueCollection); 

     var response = new Mock<HttpResponseBase>(); 
     var session = new Mock<HttpSessionStateBase>(); 
     var server = new Mock<HttpServerUtilityBase>(); 
     httpContext.Setup(c => c.Request).Returns(request.Object); 

     var u = verbs.ToString().ToUpper(); 
     httpContext.Setup(c => c.Request.RequestType).Returns(
      verbs.ToString().ToUpper() 
     ); 

     httpContext.Setup(c => c.Response).Returns(response.Object); 
     httpContext.Setup(c => c.Server).Returns(server.Object); 
     httpContext.Setup(c => c.User.Identity.Name).Returns("testclient"); 
     return httpContext.Object; 
    } 
} 

回答

7

罪魁禍首是這個行:

httpContext.Setup(c => c.Request.RequestType).Returns(
       verbs.ToString().ToUpper() 
      ); 

這在技術上是Request對象上的第二Setup,一個d即使您要在對象層次結構中「超越」它,它也會消除原始的Setup。我不確定這是否是Moq中的錯誤或期望的行爲,我之前也遇到過這種情況,並沒有得到檢查。

您可以通過將該行移動到上面設置請求的位置並直接設置它,而不是通過httpContext來解決此問題。所以,

request.Setup(c => c.RequestType).Returns(verbs.ToString().ToUpper()); 

我也注意到, 「VAR U」 你聲明沒有被使用;)

+0

真棒的感謝! – 2009-07-04 12:22:16

相關問題