如何模拟 HtmlHelper.GenerateLink

本文关键字:HtmlHelper GenerateLink 模拟 何模拟 | 更新日期: 2023-09-27 18:33:43

我有一个MVC 4控制器,它使用System.Web.Mvc.HtmlHelper.GenerateLink方法。我想对控制器进行单元测试,因此我必须模拟此方法。我正在使用最小起订量。

我的问题是我在调用 GenerateLink 方法时收到一个 NullReferenceException,我认为这是因为我的第一个参数(RequestContext)没有正确模拟。但是我不知道我必须模拟 RequestContext 的哪些属性以及如何模拟它以摆脱此错误。

目前,我将其作为模拟的设置:

var RequestContextMock = new Mock<RequestContext>();
RequestContextMock
    .Setup(x => x.HttpContext.Request.ApplicationPath) 
    .Returns(@"/");
RequestContextMock
    .Setup(x => x.HttpContext.Response.ApplyAppPathModifier(It.IsAny<string>()))
    .Returns((string s) => s);
var Routes = new RouteCollection();
Routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new {controller = "Home", action = "Index", id = UrlParameter.Optional});

但是,当执行GenerateLink方法时,这给出了NullReferenceException,因此显然我在某处缺少一些值。

编辑:被测控制器的相关部分是:

public class _AccountInfoController : Controller
{
    readonly IUserRepository _UserRepository;
    readonly IIdentityRepository  _IdentityRepository;
    public _AccountInfoController(IUserRepository userRepository,IIdentityRepository identityRepository)
    {
        this._UserRepository = userRepository;
        this._IdentityRepository = identityRepository;
    }
    [AllowAnonymous]
    public ActionResult Index(RequestContext requestContext, RouteCollection routes)
    {
        var AccountInfoModel = new AccountInfoModel();
        string Email = _IdentityRepository.GetEmailAddress();
        User User = _UserRepository.GetByEmail(Email);
        if (User != null)
        {
            string Link = HtmlHelper.GenerateLink(requestContext,routes,"Logoff",null,"Index","Logoff",null,null);

单元测试是:

    [TestMethod]
    public void HaveTenantNameInModel()
    {
        const string TenantName = "tenant name.";
        Tenant TestTenant = new Tenant {Name = TenantName};
        User TestUser = new User {CurrentTenant = (TestTenant)};
        var UserRepository = new Mock<IUserRepository>();
        UserRepository
            .Setup(p => p.GetByEmail(null))
            .Returns(TestUser);
        AccountInfoModel AccountInfoModel = new AccountInfoModel();         
        var IdentityRepository = new Mock<IIdentityRepository>();
        var ControllerUnderTest = new _AccountInfoController(UserRepository.Object,IdentityRepository.Object);
        //Mock the request context
        var RequestContextMock = new Mock<RequestContext>();
        RequestContextMock
            .Setup(x => x.HttpContext.Request.ApplicationPath) 
            .Returns(@"/");
        RequestContextMock
            .Setup(x => x.HttpContext.Response.ApplyAppPathModifier(It.IsAny<string>()))
            .Returns((string s) => s);
        var Routes = new RouteCollection();
        Routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new {controller = "Home", action = "Index", id = UrlParameter.Optional});
        dynamic Result = ControllerUnderTest.Index(RequestContextMock.Object, Routes);
        Assert.IsTrue(Result.GetType() == typeof(PartialViewResult));
        Assert.AreEqual(TenantName, Result.Model.TenantName);
    }

如何模拟 HtmlHelper.GenerateLink

您似乎收到空引用异常,因为缺少路由数据设置。

在单元测试

中,在调用系统测试之前(var 控制器UnderTest = new _AccountInfoController(....),添加行

  RequestContextMock.SetupGet(x => x.RouteData).Returns(new RouteData());

以下是测试的更新版本。

    [TestMethod]
    public void Index_WhenActionExecutes_EnsureReturnModelHasExpectedTenantName() 
    {
        const string expectedTensntName = "tenant name.";
        var fakeTenant = new Tenant { Name = expectedTensntName };
        var fakeUser = new User { CurrentTenant = (fakeTenant) };
        var userRepositoryStub = new Mock<IUserRepository>();
        userRepositoryStub.Setup(p => p.GetByEmail(It.IsAny<string>())).Returns(fakeUser);
        var identityRepositoryStub = new Mock<IIdentityRepository>();
        var sut = new AccountInfoController(userRepositoryStub.Object, identityRepositoryStub.Object);
        var requestContextStub = new Mock<RequestContext>();
        requestContextStub.Setup(x => x.HttpContext.Request.ApplicationPath).Returns(@"/");
        requestContextStub.Setup(x => x.HttpContext.Response.ApplyAppPathModifier(It.IsAny<string>()))
            .Returns((string s) => s);
        var fakeRoutes = new RouteCollection();
        fakeRoutes.MapRoute(name: "Default", url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });
        requestContextStub.SetupGet(x => x.RouteData).Returns(new RouteData());
        var result = sut.Index(requestContextStub.Object, fakeRoutes) as PartialViewResult;
        Assert.AreEqual(expectedTensntName, ((AccountInfoModel)result.Model).TenantName);
    }