2009-07-03 8 views
13

Ich habe Schwierigkeiten beim Schreiben einiger Komponententests, um einen benutzerdefinierten ModelBinder zu testen, den ich erstellt habe. Der ModelBinder, den ich versuche, Unit Test zu testen, ist der JsonDictionaryModelBinder, den ich gepostet habe here.How to Unit Testen Sie einen benutzerdefinierten ModelBinder mit Moq?

Das Problem, das ich habe, ist die Mocking alle Setup mit Moq zu bekommen. Ich bekomme immer noch Null-Ausnahmen, weil die HttpContextBase nicht richtig gespottet wird. Ich denke.

Könnte jemand mir helfen herauszufinden, was ich nicht richtig mache?

Hier ist eine Probe der Einheit Test ich arbeite, dass nicht zu schreiben, bin nicht versuchen:

[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."); 
} 

Hier ist die „FakeHttpContext“ -Methode verwendet oben:

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

Antwort

7

Der Täter ist dies Leitung:

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

Dies ist technisch ein zweites Setup auf dem Objekt anfordern, ein d es ist das Löschen der ursprünglichen Setup, obwohl Sie in der Objekthierarchie "vorbei" gehen. Ich bin mir nicht sicher, ob das ein Fehler in Moq oder gewünschtem Verhalten ist, ich bin auch schon davor gestoßen und bin nicht dazu gekommen es zu überprüfen.

Sie können es lösen, indem Sie diese Zeile dorthin verschieben, wo Sie Ihre Anfrage oben einrichten, und sie direkt einrichten, anstatt den httpContext durchzugehen. So

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

ich auch feststellen, dass die "var u", die Sie erklären nicht verwendet wird;)

+0

Ehrfürchtig Dank! –