如何使用URLHelp在静态类中模拟静态方法? (MOQ)

时间:2009-10-03 20:42:09

标签: model-view-controller moq

我有一个扩展方法。任何人都可以帮我学习如何用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;
    }
非常感谢。

2 个答案:

答案 0 :(得分:1)

UrlHelper.RequestContext属性是非虚拟的。据我所知,在这种情况下,Moq不会有任何帮助。

您可以为实现接口的UrlHelper创建一个包装类,但这似乎无法使用扩展方法。

如果你有商业计划的预算,

Typemock可能会做你想要的。 (我没有尝试过;我自己使用Moq。)

另一个选择是针对此方法编写集成测试;虽然他们的运行速度比单元测试慢,但我怀疑这种方法不太可能经常出版。

更大的问题是与UrlHelper的耦合会降低应用程序其余部分的可测试性。也许其他海报可以提出这个问题的答案。

答案 1 :(得分:1)

正如TrueWill所指出的,你不能直接使用Moq和UrlHelper.RequestContext,因为它不是虚拟的。另一方面,UrlHelper是一个公共类,您可以将其实例化以用于单元测试。

然而,在某些时候,您将需要分配一个HttpContextBase来创建UrlHelper,Moq可以帮助您做到这一点。

这是一个测试,表明我至少可以编写一个调用GetBaseUrl的单元测试而不会抛出任何异常:

[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
}

然而,这不是最简单的编写和维护单元测试,因此我支持TrueWill的评论,如果你将UrlHelper隐藏在界面后面,你可能会让自己的生活更简单。