我有一个扩展方法。任何人都可以帮我学习如何用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;
}
非常感谢。
答案 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隐藏在界面后面,你可能会让自己的生活更简单。