Wai Yan Hein Wai Yan Hein - 23 days ago 6
C# Question

UrlHelper class throws null exception in Asp.net mvc

I am developing an Asp.net mvc web application. I am doing Unit Test to my application. I am using Moq to mock objects. I am trying to mock Url helper class. I found this link- asp.net mvc: how to mock Url.Content("~")?. Using that class, I can mock

UrlHelper
class in unit test. Please see what I did below.

I created a
BaseController
like this

public class BaseController : Controller
{
private IUrlHelper _urlHelper;

public new IUrlHelper Url
{
get { return _urlHelper; }
set { _urlHelper = value; }
}
}


Here is the
IUrlHelper
interface/abstraction

public interface IUrlHelper
{
string Action(string actionName);
string Action(string actionName, object routeValues);
string Action(string actionName, string controllerName);
string Action(string actionName, RouteValueDictionary routeValues);
string Action(string actionName, string controllerName, object routeValues);
string Action(string actionName, string controllerName, RouteValueDictionary routeValues);
string Action(string actionName, string controllerName, object routeValues, string protocol);
string Action(string actionName, string controllerName, RouteValueDictionary routeValues, string protocol, string hostName);
string Content(string contentPath);
string Encode(string url);
string RouteUrl(object routeValues);
string RouteUrl(string routeName);
string RouteUrl(RouteValueDictionary routeValues);
string RouteUrl(string routeName, object routeValues);
string RouteUrl(string routeName, RouteValueDictionary routeValues);
string RouteUrl(string routeName, object routeValues, string protocol);
string RouteUrl(string routeName, RouteValueDictionary routeValues, string protocol, string hostName);
}


I mock the
Url.Content()
in the unit test like this

Mock<IUrlHelper> urlHelperMock = new Mock<IUrlHelper>();
urlHelperMock
.Setup(x => x.Content(It.IsAny<string>()))
.Returns<string>(x => "~/" + x);// Mock Content method of Url Helper


Test run successfully and working fine. The problem is I cannot use it in real time application. I mean when I run my app and call Url.Content("path"), it throws null exception.

For example

public class ExampleController : BaseController
{
public string GetPath()
{
return Url.Content("~/Path/To/File");
}
}


Url.Content
in this code throws null exception. Please why? What is wrong? It is working fine in unit test. Please help me, how can I fix that code? Code should be working. Right?

Answer

In this case there really isn't a need to abstract the UrlHelper. Just mock up the helper for the test to do what is required.

For example, assuming

public class ExampleController : Controller {
    public string GetContent() {
       return Url.Content("~/Path/To/File");
    }
}

Here is a test that mocks the UrlHelper using moq to work just like in original example

[TestClass]
public class UrlHelperTest {
    [TestMethod]
    public void MockUrlHelper() {
        //Arrange            
        var expectedPath = "~/Path/To/File";
        var expectedContent = "<p>Fake content here<p>";
        var urlHelperMock = new Mock<UrlHelper>();
        urlHelperMock
            .Setup(m => m.Content(expectedPath))
            .Returns(expectedContent)
            .Verifiable();

        var sut = new ExampleController();
        sut.Url = urlHelperMock.Object; //Set mock UrlHelper        

        //Act
        var actualContent = sut.GetContent();

        //Assert
        urlHelperMock.Verify();
        Assert.AreEqual(expectedContent, actualContent);
    }
}

So now the test can be performed and also the framework will populate the necessary controller properties in production because technically nothing was changed from the original framework to custom abstractions.

Comments