3

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.

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. It is working fine in unit test. How can I fix that code?

halfer
  • 19,824
  • 17
  • 99
  • 186
Wai Yan Hein
  • 13,651
  • 35
  • 180
  • 372
  • This example has shown how it mocks the interface for testing but don't show how it is implemented for production code. chances are no production implementation was done so it is null for live execution. – Nkosi Nov 12 '16 at 15:08

1 Answers1

5

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.

Nkosi
  • 235,767
  • 35
  • 427
  • 472