2009-10-03 43 views
1

我有一个扩展方法。任何人都可以帮助我如何用Moq测试这种方法吗?如何使用URLHelp模拟静态类中的静态方法? (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; 
    } 

非常感谢。

回答

1

正如TrueWill所指出的那样,您不能直接在UrlHelper.RequestContext中使用Moq,因为它不是虚拟的。另一方面,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隐藏在界面后面,您可能会使自己的生活变得更简单。

+0

+1:比我的更好的答案。 – TrueWill

+0

非常感谢。 –

+0

关于使用接口在此播客中使用网关模式来分离依赖关系有一个很好的讨论:http://www.slickthought.net/post/2009/04/03/New-Spaghetti-Code-Podcast-ndash3b-Donn -Felker会谈,Mocking.aspx – TrueWill

1

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

您可以为UrlHelper创建一个包装类,它实现了一个接口,但是这看起来会破坏使用扩展方法的目的。

Typemock可能会做你想做的,如果你有商业计划的预算。 (我没有尝试过;我自己使用Moq。)

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

一个更大的问题是耦合到UrlHelper,从而降低应用程序其余部分的可测试性。也许其他海报可以建议这个问题的答案。

+0

+1用于暗示将UrlHelper隐藏在界面后面。 –

相关问题