没有简单的方法来测试 helper.Action 是否使用正确的参数调用。这是因为正如一些 cmets 指出的那样,HtmlHelper 也不是可模拟的,Action 也是静态扩展。但是您可以使用变通方法测试特定场景,例如根据您的问题。
它只需要一个可以模拟 Action 方法返回的测试
特别是某些东西,因此可以断言它正在被调用
正确的参数。
虽然由于静态特性,这并不完全可能,但我们可以使用不同的技术来验证是否使用正确的参数调用了 Action。
这只是指导,我还没有完全测试我的代码。我知道它可以在测试环境中工作,但我不完全确定这会在生产代码执行期间产生正确的结果。如果不是,我很乐意再看一遍..
首先,我将创建一个允许我覆盖 helper.Action 方法的类。
public class HtmlHelperActionInvoker {
public virtual MvcHtmlString InvokeAction(HtmlHelper helper, string action, string controller) {
return helper.Action(action, controller);
}
}
然后在您的 Html 助手类中,我将添加静态构造函数和一个委托/函数,它允许我在测试执行期间设置我自己的 HtmlHelpActionInvoker 版本。
public static class SomeHtmlHelperClass
{
static SomeHelperClass() {
HtmlHelperActionFunc = () => new HtmlHelperActionInvoker();
}
public static Func<HtmlHelperActionInvoker> HtmlHelperActionFunc { get; set; }
public static MvcHtmlString RenderCMSObject(this HtmlHelper helper, CMSObject cmsObject)
{
var actionName = string.IsNullOrEmpty(cmsObject.ActionName)
? "Index"
: cmsObject.ActionName;
var controllerName = string.IsNullOrEmpty(cmsObject.ControllerName)
? "Default"
: cmsObject.ControllerName;
var helperAction = HtmlHelperActionFunc();
return helperAction.InvokeAction(helper, actionName, controllerName);
}
}
我相信静态 ctro 会在生产代码执行期间执行一次并设置一次 HtmlHelperActionInvoker 实例。后续请求将重用此实例。 (正如我之前提到的,您可能需要对此进行更多测试)
现在是单元测试
我们将使用一种称为Extract & Override 的技术。
在您的测试区域中创建 HtmlHelperActionInvoker 的可测试版本。这不是假对象/存根/模拟。这是 HtmlHelperActionInvoker 的可测试版本。并且只使用一个方法调用了预期的参数。
public class TesatableHtmlHelperAction : HtmlHelperActionInvoker
{
public string Controller { get; set; }
public string Action { get; set; }
public override MvcHtmlString InvokeAction(HtmlHelper helper, string action, string controller) {
Action = action;
Controller = controller;
return new MvcHtmlString("");
}
}
在单元测试中,我们将设置可测试的 TesatableHtmlHelperAction,以便 SUT(被测系统)执行可测试的版本。 (注意:它仍然被认为是真实的,因为我们覆盖了真正的 HtmlHelperActionInvoker 的行为)
[TestMethod]
public void HtmlHelperActionRenderCMSObject_Execute_EnsureInvokeActionCalledWithExpectedControlerAndActionName()
{
//Arrange
var fakecmsObject = new CMSObject() { ActionName = "foo", ControllerName = "bar" };
var testableHtmlHelperAction = new TesatableHtmlHelperAction();
SomeHelperClass.HtmlHelperActionFunc = () => testableHtmlHelperAction;
// Act
SomeHelperClass.RenderCMSObject(null, fakecmsObject);
// Verify
Assert.AreEqual<string>(fakecmsObject.ActionName, testableHtmlHelperAction.Action);
Assert.AreEqual<string>(fakecmsObject.ControllerName, testableHtmlHelperAction.Controller);
}