tags:

views:

382

answers:

2

I have a extension method. Can any one help me how to test this method with Moq?

 public static string GetBaseUrl(this UrlHelper urlHelper)
    {
        Uri contextUri = new Uri(urlHelper.RequestContext.HttpContext.Request.Url, urlHelper.RequestContext.HttpContext.Request.RawUrl);
        UriBuilder realmUri = new UriBuilder(contextUri) { Path = urlHelper.RequestContext.HttpContext.Request.ApplicationPath, Query = null, Fragment = null };
        string url = realmUri.Uri.AbsoluteUri;

        if (url.EndsWith("/"))
        {
            url = url.Remove(url.Length - 1, 1); 
        }

        return url;
    }

many thanks.

+1  A: 

The UrlHelper.RequestContext property is non-virtual. Moq isn't going to be of help in this case, to the best of my knowledge.

You could create a wrapper class for UrlHelper that implements an interface, but that would seem to defeat the purpose of using an extension method.

Typemock would probably do what you want, if you have the budget for a commercial program. (I haven't tried it; I use Moq myself.)

Another option would be to write integration tests against this method; while they would run more slowly than unit tests, I suspect this method is unlikely to version often.

A larger issue is coupling to UrlHelper reducing testability in the rest of your application. Perhaps other posters can suggest answers to that issue.

TrueWill
+1 for suggesting to hide UrlHelper behind an interface.
Mark Seemann
+1  A: 

As TrueWill points out, you can't use Moq directly with UrlHelper.RequestContext because it isn't virtual. On the other hand, UrlHelper is a public class that you can instantiate for use with unit testing.

At some point, however, you will encounter the need to assign a HttpContextBase to create the UrlHelper, and Moq can help you to do that.

Here's a test that shows that I can at least write a unit test that invokes your GetBaseUrl without throwing any exceptions:

[TestMethod]
public void Test1()
{
    var httpCtxStub = new Mock<HttpContextBase>();
    httpCtxStub.SetupGet(x => x.Request).Returns(() =>
        {
            var reqStub = new Mock<HttpRequestBase>();
            reqStub.SetupGet(r => r.RawUrl).Returns("http://foo");
            reqStub.SetupGet(r => r.Url).Returns(new Uri("http://foo"));
            return reqStub.Object;
        });

    var requestCtx = new RequestContext(httpCtxStub.Object, new RouteData());
    var urlHelper = new UrlHelper(requestCtx, new RouteCollection());

    var result = urlHelper.GetBaseUrl();

    // Assert something
}

However, this isn't the simplest unit test to write and maintain, so I support TrueWill's comment that you might make life simpler for yourself if you hide UrlHelper behind an interface.

Mark Seemann
+1: A better answer than mine.
TrueWill
Thank you very much.
Daoming Yang
There's a nice discussion of using interfaces to decouple dependencies using a Gateway pattern of sorts in this podcast: http://www.slickthought.net/post/2009/04/03/New-Spaghetti-Code-Podcast-ndash3b-Donn-Felker-Talks-Mocking.aspx
TrueWill