我正在尝试单元测试自定义动作结果。我最近观看了Jimmy Bogard出色的MvcConf视频(“让你的控制器节食”)http://www.viddler.com/explore/mvcconf/videos/1/,并开始尝试并实施一些自定义操作结果。我已经管理了这个没有问题,ActionResult在运行时正常工作,但我无法尝试单元测试它们。如何对自定义动作进行单元测试结果
不幸的是,在代码下载中,没有针对Jimmy自定义操作方法的单元测试......这让我感到惊讶。
我意识到action方法只是返回ActionResult类型的实例和它实际调用ExecuteResult方法的MVC框架,这当然在运行单元测试时不可用。所以我的单元测试现在只是创建一个我自定义的ActionResult的实例,然后我调用ExecuteResult。
Unfortunatley在我自定义的ActionResult的ExecuteResult方法中,它也调用了我通过它的ViewResult的ExecuteResult方法。那时它爆炸了。我应该如何嘲笑/剔除这些东西才能让我的单元测试工作?
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 = "[email protected]"
};
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中显示为出现问题。
我知道我应该以某种方式存根/嘲弄,但我似乎无法解决此问题。
Thaks戴夫,这是非常有意义的。我从Jimmy的例子中看到了他所展示的MvcConf视频的代码,他实际上在最初的ActionResult的ExecuteMethod方法中调用了成功和失败ActionResults的ExecuteMethod。但是这个解决方案要好得多。它的一切都像魅力一样工作。实际上,我已经在行动书中获得了两个版本的MVC。也许我应该回去做更多的研究:) – 2010-08-06 18:12:12
它*就这么发生了*,我今天正在阅读关于测试和自定义ActionResults的章节。情缘! – 2010-08-06 18:19:53