C# UrlHelper mock不工作

C# UrlHelper mock不工作,c#,asp.net-mvc,unit-testing,moq,urlhelper,C#,Asp.net Mvc,Unit Testing,Moq,Urlhelper,我正在尝试编写一个通过的单元测试,但是我的测试调用的方法调用另一个方法,该方法使用UrlHelper类生成URL。调用urlHelper.Action的结果将继续返回null 我已经尝试过模拟(使用Moq)我认为这个控制器需要的所有组件,但我仍然得到null 单元测试类 [TestFixtureSetUp] public void Configure_Defaults() { var mockHttpContextBase = new Mock<HttpContextBase&g

我正在尝试编写一个通过的单元测试,但是我的测试调用的方法调用另一个方法,该方法使用
UrlHelper
类生成URL。调用
urlHelper.Action
的结果将继续返回
null

我已经尝试过模拟(使用Moq)我认为这个控制器需要的所有组件,但我仍然得到
null

单元测试类

[TestFixtureSetUp]
public void Configure_Defaults()
{

    var mockHttpContextBase = new Mock<HttpContextBase>();

    var mockRequest = new Mock<HttpRequestBase>();

    var mockControllerContext = new Mock<ControllerContext>();

    var mockWebRoutingRequestContrext = new Mock<RequestContext>();

    mockRequest
        .Setup(request => request.Url)
        .Returns(new Uri("http://dev.fleepos.local/Register"));

    mockHttpContextBase
        .Setup(httpContext => httpContext.Request)
        .Returns(mockRequest.Object);

    mockWebRoutingRequestContrext
        .Setup(request => request.HttpContext)
        .Returns(mockHttpContextBase.Object);

    mockWebRoutingRequestContrext
        .Setup(request => request.RouteData)
        .Returns(new RouteData());

    var urlHelper = new UrlHelper(mockWebRoutingRequestContrext.Object);

    mockControllerContext
        .Setup(controllerContext => controllerContext.HttpContext)
        .Returns(mockHttpContextBase.Object);


    _registerController = new RegisterController() {ControllerContext = mockControllerContext.Object, Url = urlHelper};

}

[Test]
public void Display_Validate_Account_Page_On_Successful_Registration()
{
    //act
    var result = (RedirectToRouteResult)_registerController.Register(_userRegisterationViewModel);

    //assert
    Assert.That(result.RouteValues["action"], Is.EqualTo("ValidateAccount"));
}

控制器已经有一个
UrlHelper Url
属性,可以对该属性进行模拟以执行您想要的操作。通过在控制器操作调用的控制器方法中创建一个
新的UrlHelper
,就失去了替换模拟/伪的机会

首先更新控制器操作调用的控制器方法,使其对测试友好

private string GenerateActionLink(string actionName, string token, string username) {
    string validationLink = null;
    if (Request.Url != null) {
        validationLink = Url.Action(actionName, "Register",
            new { Token = token, Username = username },
            Request.Url.Scheme);
    }

    return validationLink;
}
现在对控制器的UrlHelper有了更多的控制。UrlHelper也可以被模拟并传递给控制器上下文

下面是上面解释的一个最小完整示例

[TestClass]
public class UrlHelperTest {
    [TestMethod]
    public void MockUrlHelper() {
        //Arrange
        var requestUrl = new Uri("http://myrequesturl");
        var request = Mock.Of<HttpRequestBase>();
        var requestMock = Mock.Get(request);
        requestMock.Setup(m => m.Url).Returns(requestUrl);

        var httpcontext = Mock.Of<HttpContextBase>();
        var httpcontextSetup = Mock.Get(httpcontext);
        httpcontextSetup.Setup(m => m.Request).Returns(request);


        var actionName = "MyTargetActionName";
        var expectedUrl = "http://myfakeactionurl.com";
        var mockUrlHelper = new Mock<UrlHelper>();
        mockUrlHelper
            .Setup(m => m.Action(actionName, "Register", It.IsAny<object>(), It.IsAny<string>()))
            .Returns(expectedUrl)
            .Verifiable();

        var sut = new MyController();
        sut.Url = mockUrlHelper.Object;
        sut.ControllerContext = new ControllerContext {
            Controller = sut,
            HttpContext = httpcontext,
        };

        //Act
        var result = sut.MyAction();

        //Assert
        mockUrlHelper.Verify();
    }

    public class MyController : Controller {
        [HttpPost]
        public ActionResult MyAction() {
            var link = GenerateActionLink("MyTargetActionName", string.Empty, string.Empty);

            return View((object)link);
        }

        private string GenerateActionLink(string actionName, string token, string username) {
            string validationLink = null;
            if (Request.Url != null) {
                var encodedToken = EncodedUrlParameter(token);
                var url = Url.Action(actionName, "Register", new { Token = encodedToken, Username = username }, Request.Url.Scheme);
                validationLink = url;
            }

            return validationLink;
        }

        private string EncodedUrlParameter(string token) {
            return "Fake encoding";
        }

    }
}
[TestClass]
公共类UrlHelperTest{
[测试方法]
public void MockUrlHelper(){
//安排
var requestUrl=新Uri(“http://myrequesturl");
var request=Mock.Of();
var requestMock=Mock.Get(请求);
Setup(m=>m.Url).Returns(requestUrl);
var httpcontext=Mock.Of();
var httpcontextSetup=Mock.Get(httpcontext);
httpcontextSetup.Setup(m=>m.Request).Returns(Request);
var actionName=“MyTargetActionName”;
var expectedUrl=”http://myfakeactionurl.com";
var mockUrlHelper=new Mock();
mockUrlHelper
.Setup(m=>m.Action(actionName,“Register”、It.IsAny()、It.IsAny())
.返回(预期返回)
.可验证();
var sut=新的MyController();
Url=mockUrlHelper.Object;
sut.ControllerContext=新的ControllerContext{
控制器=sut,
HttpContext=HttpContext,
};
//表演
var result=sut.MyAction();
//断言
mockUrlHelper.Verify();
}
公共类MyController:Controller{
[HttpPost]
公共行动结果MyAction(){
var link=GenerateActionLink(“MyTargetActionName”,string.Empty,string.Empty);
返回视图((对象)链接);
}
私有字符串GenerateActionLink(字符串actionName、字符串令牌、字符串用户名){
字符串validationLink=null;
if(Request.Url!=null){
var encodedToken=EncodedUrlParameter(令牌);
var url=url.Action(actionName,“Register”,new{Token=encodedToken,Username=Username},Request.url.Scheme);
validationLink=url;
}
返回验证链接;
}
专用字符串编码器参数(字符串令牌){
返回“假编码”;
}
}
}

Action方法的模拟版本是在哪里定义的?不在哪里,只是模拟了控制器并请求@jeroenheier您不能模拟扩展方法。。(UrlHelper.Action是扩展方法)
[TestClass]
public class UrlHelperTest {
    [TestMethod]
    public void MockUrlHelper() {
        //Arrange
        var requestUrl = new Uri("http://myrequesturl");
        var request = Mock.Of<HttpRequestBase>();
        var requestMock = Mock.Get(request);
        requestMock.Setup(m => m.Url).Returns(requestUrl);

        var httpcontext = Mock.Of<HttpContextBase>();
        var httpcontextSetup = Mock.Get(httpcontext);
        httpcontextSetup.Setup(m => m.Request).Returns(request);


        var actionName = "MyTargetActionName";
        var expectedUrl = "http://myfakeactionurl.com";
        var mockUrlHelper = new Mock<UrlHelper>();
        mockUrlHelper
            .Setup(m => m.Action(actionName, "Register", It.IsAny<object>(), It.IsAny<string>()))
            .Returns(expectedUrl)
            .Verifiable();

        var sut = new MyController();
        sut.Url = mockUrlHelper.Object;
        sut.ControllerContext = new ControllerContext {
            Controller = sut,
            HttpContext = httpcontext,
        };

        //Act
        var result = sut.MyAction();

        //Assert
        mockUrlHelper.Verify();
    }

    public class MyController : Controller {
        [HttpPost]
        public ActionResult MyAction() {
            var link = GenerateActionLink("MyTargetActionName", string.Empty, string.Empty);

            return View((object)link);
        }

        private string GenerateActionLink(string actionName, string token, string username) {
            string validationLink = null;
            if (Request.Url != null) {
                var encodedToken = EncodedUrlParameter(token);
                var url = Url.Action(actionName, "Register", new { Token = encodedToken, Username = username }, Request.Url.Scheme);
                validationLink = url;
            }

            return validationLink;
        }

        private string EncodedUrlParameter(string token) {
            return "Fake encoding";
        }

    }
}