Как Unit Test пользовательский ModelBinder с использованием Moq?
У меня возникли трудности с написанием некоторых тестов Unit для тестирования пользовательского ModelBinder, который я создал. ModelBinder Я пытаюсь использовать Unit Test JsonDictionaryModelBinder, который я разместил здесь.
Проблема, с которой я столкнулась, - это получить Mocking all setup с помощью Moq. Я продолжаю получать Null Exceptions из-за того, что HttpContextBase не исправляется правильно. Я думаю.
Может ли кто-нибудь помочь мне разобраться, что я не делаю с коррекцией?
Вот пример Unit Test, который я пытаюсь написать, который не работает:
[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;
}
}
Ответы
Ответ 1
Преступником является эта строка:
httpContext.Setup(c => c.Request.RequestType).Returns(
verbs.ToString().ToUpper()
);
Это технически второй Setup
объект Request, и он уничтожает исходный Setup
, даже если вы идете в прошлое его в иерархии объектов. Я не уверен, является ли это ошибкой в Moq или желаемом поведении, я столкнулся с этим раньше и не стал проверять его.
Вы можете решить эту проблему, переместив эту строку туда, где вы настраиваете свой запрос выше, и настраиваете его напрямую, а не через httpContext. Таким образом,
request.Setup(c => c.RequestType).Returns(verbs.ToString().ToUpper());
Я также замечаю, что "var u", который вы объявляете, не используется;)