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?

1
  • 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. Commented Nov 12, 2016 at 15:08

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.