Я пытаюсь провести модульное тестирование результата пользовательского действия. Недавно я смотрел превосходное видео Джимми Богарда на MvcConf («положи свои контроллеры на диету») http://www.viddler.com/explore/mvcconf/videos/1/ и начал пытаться реализовать некоторые результаты специальных действий. Я справился с этим без проблем, ActionResult прекрасно работает во время выполнения, но у меня возникают проблемы при попытке их модульного тестирования.
К сожалению, в загрузке кода нет модульных тестов для методов пользовательских действий Джимми ... что вызывает у меня удивление.
Я понимаю, что методы действия просто возвращают экземпляры типов ActionResult и его среду MVC, которая фактически вызывает метод ExecuteResult, который, конечно, недоступен при запуске модульного теста. Поэтому мой модульный тест сейчас просто создает экземпляр моего пользовательского ActionResult, и я затем вызываю ExecuteResult.
К сожалению, в методе ExecuteResult моего пользовательского ActionResult он также вызывает метод ExecuteResult объекта ViewResult, который я ему передал. В этот момент он взрывается. Как я должен насмехаться над этими вещами, чтобы мой модульный тест работал?
public class SendToAFriendActionResult : ActionResult
{
public const string INVALID_CAPTCHA = "You don't appear to have filled out the two words from the security image correctly to prove you're a human. Please try again.";
public const string INVALID_MODEL_STATE = "You don't appear to have filled out all the details correctly. Please try again.";
public const string CONTACT_FAIL = "Unfortunately we experiend a problem sending the link. Please try again later.";
public const string SEND_TO_A_FRIEND_FAIL_KEY = "ContactFail";
private RedirectResult _success;
private ViewResult _failure;
private readonly SendToAFriendModel _model;
private readonly bool _captchaValid;
private readonly MessageBuilderServiceBase _mbs;
public RedirectResult Success
{
get { return _success; }
set { _success = value; }
}
public ViewResult Failure
{
get { return _failure; }
set { _failure = value; }
}
public SendToAFriendActionResult(RedirectResult success, ViewResult failure, SendToAFriendModel model, bool captchaValid, MessageBuilderServiceBase mbs)
{
_success = success;
_failure = failure;
_model = model;
_captchaValid = captchaValid;
_mbs = mbs;
}
public override void ExecuteResult(ControllerContext context)
{
if (!_captchaValid)
{
Failure.TempData[SEND_TO_A_FRIEND_FAIL_KEY] = INVALID_CAPTCHA;
// On reaching this point I receive the error
// Object reference not set to an instance of an object
// as the MVC framework calls FindView
Failure.ExecuteResult(context);
return;
}
if (!context.Controller.ViewData.ModelState.IsValid)
{
Failure.TempData[SEND_TO_A_FRIEND_FAIL_KEY] = INVALID_MODEL_STATE;
Failure.ExecuteResult(context);
return;
}
_mbs.RecipientEmailAddress = _model.EmailRecipient;
_mbs.SendersName = _model.SendersName;
_mbs.Url = _model.URL;
var result = _mbs.sendMessage();
if (!result)
{
Failure.TempData[SEND_TO_A_FRIEND_FAIL_KEY] = CONTACT_FAIL;
Failure.ExecuteResult(context);
return;
}
Success.ExecuteResult(context);
}
}
Вот начало моего юнит-теста ...
IMessageService _emailMessageSerivce;
IGalleryRepository _repository;
var stfModel = new SendToAFriendModel
{
SendersName = "Someone",
URL = "http://someurl.com",
EmailRecipient = "a-friend@somewherelse.com"
};
var failure = new ViewResult() {ViewName ="SendToFriend"};
const bool captchaValid = false;
var fakeControlllerContext = MockRepository.GenerateStub<ControllerContext>(null);
var stf = new SendToAFriendActionResult(null, failure, stfModel, captchaValid, null);
stf.ExecuteResult(fakeControlllerContext);
Я поместил комментарии в SUT, чтобы показать, где возникает проблема.
Я знаю, что должен как-то ошарашить / издеваться, но я просто не могу решить эту проблему.