Хорошо, поэтому я пытаюсь проверить результат контроллера, чтобы убедиться, что он возвращает правильные значения, но я столкнулся с рядом проблем с насмешливыми контекстами контроллера. Все, что я хочу сделать, это проверить, входит ли кто-нибудь на страницу на странице, если JsonResult имеет успех = true. Однако в контроллере я сериализую частичный вид и возвращаю некоторый HTML, содержащий все данные, относящиеся к номеру запроса. Мне комфортно настраивать ожидаемые результаты в результате json, но я даже не могу пройти тест до этого. При сериализации частичного обзора тест зависает. Мне все равно не нужно проверять это, но я не знаю, как работать с результатом этой функции, кроме создания некоторых подделок для контекста controller, и пусть он ищет сериализацию представления.Как протестировать действие контроллера, которое сериализует представление
Вот это контроллер
[HttpPost]
[RecaptchaControlMvc.CaptchaValidator]
public JsonResult GetPublicInformation(PublicPortalViewModel model, bool captchaValid)
{
if (captchaValid == true)
{
//check to see if their is a request number to look up the request by
if (model.RequestNumber != null)
{
//fill model data using by calling the service
model = _service.GetPublicPortalData(model);
var content = base.SerializeView("DisplayPublicInformation", model);
return Json(new { success = true, htmlContent = content });
}
else
{
return Json(new { success = false, htmlContent = "<span style=\"color: red;\">No request was found with that number, please enter a valid request number.</span>" });
}
}
else
{
return Json(new { success = false, htmlContent = "<span style=\"color: red;\">Please enter a valid Captcha Value</span>" });
}
}
В частности, я имею проблемы с этой линии:
var content = base.SerializeView("DisplayPublicInformation", model);
Вот определение этой функции:
protected internal virtual string SerializeView(string viewName, object model)
{
if (string.IsNullOrEmpty(viewName))
viewName = ControllerContext.RouteData.GetRequiredString("action");
this.ViewData.Model = model;
using (var sw = new StringWriter())
{
// keep getting null reference errors on this line when I write my tests .
var viewResult = ViewEngines.Engines.FindPartialView(this.ControllerContext, viewName);
var viewContext = new ViewContext(this.ControllerContext, viewResult.View, this.ViewData, this.TempData, sw);
// render the view into the stringwriter class
viewResult.View.Render(viewContext, sw);
// output the rendered string
return sw.GetStringBuilder().ToString();
}
}
Вот мой тест который я извиняюсь за то, что я был настолько грязным, но я хотел опубликовать там, где я сейчас. Я знаю, что есть больше кода, чем нужно.
private PartialViewResult _result;
private Mock<HttpContextBase> _mockHttpContext;
private HttpContextBase _httpContext;
private RouteData _routeData;
private RouteData _parentRouteData;
protected Mock<HttpContextBase> HttpContextBaseMock;
protected Mock<HttpRequestBase> HttpRequestMock;
protected Mock<HttpResponseBase> HttpResponseMock;
[Test]
public void GetPublicInformationValidRequestNumber()
{
var sut = new PublicPortalController();
SetupRouteData();
HttpContextBaseMock = new Mock<HttpContextBase>();
HttpContextBaseMock.SetupAllProperties();
HttpRequestMock = new Mock<HttpRequestBase>();
HttpResponseMock = new Mock<HttpResponseBase>();
HttpContextBaseMock.SetupGet(x => x.Request).Returns(HttpRequestMock.Object);
HttpContextBaseMock.SetupGet(x => x.Response).Returns(HttpResponseMock.Object);
var browser = new Mock<HttpBrowserCapabilitiesBase>(MockBehavior.Strict);
var request = new Mock<HttpRequestBase>(MockBehavior.Strict);
var response = new Mock<HttpResponseBase>(MockBehavior.Strict);
var session = new Mock<HttpSessionStateBase>(MockBehavior.Strict);
var server = new Mock<HttpServerUtilityBase>(MockBehavior.Strict);
var cookies = new HttpCookieCollection();
var items = new ListDictionary();
var mockViewEngine = new Mock<IViewEngine>();
Mock<IView> view = new Mock<IView>();
var viewResult = new ViewEngineResult(new[] { "location1", "location2" });
mockViewEngine
.Setup(x => x.FindView(It.IsAny<ControllerContext>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>()))
.Returns(viewResult);
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(mockViewEngine.Object);
browser.Setup(b => b.IsMobileDevice).Returns(false);
request.Setup(r => r.Cookies).Returns(cookies);
request.Setup(r => r.ValidateInput());
request.Setup(r => r.UserAgent).Returns("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11");
response.Setup(r => r.Cookies).Returns(cookies);
request.Setup(r => r.Browser).Returns(browser.Object);
HttpContextBaseMock.Setup(ctx => ctx.Items).Returns(items);
var routes = new RouteCollection();
var ControllerContext = new Mock<ControllerContext>(HttpContextBaseMock.Object, _routeData, sut);
var controller = new Mock<PublicPortalController>();
ControllerContext.SetupGet(c => c.Controller).Returns(controller.Object);
ControllerContext.SetupGet(c => c.HttpContext).Returns(HttpContextBaseMock.Object);
sut.Url = new UrlHelper(new RequestContext(HttpContextBaseMock.Object, _routeData), routes);
sut.ControllerContext = ControllerContext.Object;
var basecontroller = new Mock<RequestITBaseController>();
var fakePublicPortalViewModel = new Mock<PublicPortalViewModel>();
fakePublicPortalViewModel.Setup(m => m.RequestNumber).Returns("23");
bool captchaValid = true;
basecontroller.Setup(c => c.SerializeView("DisplayPublicInformation", fakePublicPortalViewModel)).Returns("");
var result = sut.GetPublicInformation(fakePublicPortalViewModel.Object, captchaValid) as JsonResult;
dynamic jsonObject = result.Data;
Assert.IsTrue(jsonObject.success);
}
private void SetupRouteData()
{
SetupParentRouteData();
var viewContext = new ViewContext { RouteData = _parentRouteData };
_routeData = new RouteData();
_routeData.Values.Add("controller", "PublicPortalController");
_routeData.Values.Add("action", "GetPublicInformation");
_routeData.DataTokens["ParentActionViewContext"] = viewContext;
}
private void SetupParentRouteData()
{
_parentRouteData = new RouteData();
_parentRouteData.Values.Add("controller", "PublicPortalController");
_parentRouteData.Values.Add("action", "Index");
}
Hahahahahah, действительно смеясь. Я очень благодарен за ваш ответ, однако для меня немного новое, чтобы разделить ранее существовавшую функцию и добавить новую перегрузку конструктора, чтобы написать успешный тестовый пример. Я чувствую, что я просто нарушил некоторые принципы кодирования, чтобы получить результат, который я хотел, это обычная практика тестирования? Я только начал с автоматизированного тестирования модулей на этой неделе, поэтому я не уверен, что я только что получил свой первый урок в Test Driven Development или если это одно решение, которое не должно быть сделано в будущем? –
@HunterNelson это, вероятно, одна из тех серых областей, где есть аргументы в любом случае. Но я нашел самый простой способ написать тестируемый код, чтобы как можно больше абстрагировать зависимости, гораздо проще издеваться над чем-то, о чем вы знаете, чем о чем-то, чего у вас нет. Насколько я знаю, это также не нарушает каких-либо принципов кодирования, но, скорее всего, поддерживает принципы S, I и D в принципах SOLID. –