我很擅长使用moq。我正在为HttpModule
创建一些单元测试用例,一切正常,直到我点击static
属性,如下所示
this.applicationPath = (HttpRuntime.AppDomainAppVirtualPath.Length > 1) ? HttpRuntime.AppDomainAppVirtualPath : String.Empty;
我不知道如何为static
类和HttpRuntime.AppDomainAppVirtualPath
之类的属性创建模拟。我从moq获得的示例代码已经模拟了context
,request
和response
。如果有人能帮助我,我将不胜感激。
答案 0 :(得分:60)
Moq无法伪造静态成员。
作为一种解决方案,您可以创建一个包含静态属性的包装类(适配器模式)并伪造其成员 例如:
public class HttpRuntimeWrapper
{
public virtual string AppDomainAppVirtualPath
{
get
{
return HttpRuntime.AppDomainAppVirtualPath;
}
}
}
在生产代码中,您可以访问此类而不是HttpRuntime
并伪造此属性:
[Test]
public void AppDomainAppVirtualPathTest()
{
var mock = new Moq.Mock<HttpRuntimeWrapper>();
mock.Setup(fake => fake.AppDomainAppVirtualPath).Returns("FakedPath");
Assert.AreEqual("FakedPath", mock.Object.AppDomainAppVirtualPath);
}
另一种解决方案是使用隔离框架(如Typemock Isolator),您可以伪造静态类和成员。
例如:
Isolate.WhenCalled(() => HttpRuntime.AppDomainAppVirtualPath)
.WillReturn("FakedPath");
免责声明 - 我在Typemock工作
答案 1 :(得分:11)
你不能使用Moq的Moq静态方法。
实际上这不是坏事,静态方法和类确实有它们的位置,但对于逻辑,它们使单元测试变得困难。当然,在使用其他库时你会遇到它们。要解决这个问题,您需要在静态代码周围编写adapter(包装器),并提供一个接口。例如:
// Your static class - hard to mock
class StaticClass
{
public static int ReturnOne()
{
return 1;
}
}
// Interface that you'll use for a wrapper
interface IStatic
{
int ReturnOne();
}
注意,我已经省略了使用IStatic作为生产代码的具体类。所有
它将是一个使用IStatic的类,您的生产代码将使用此类,而不是上面的StaticClass
。
然后用Moq:
var staticMock = new Mock<IStatic>();
staticMock.Setup(s => s.ReturnOne()).Returns(2);
答案 2 :(得分:3)
如前面的答案所述,你不能在静态方法上使用MoQ,如果需要,最好的方法是在静态类周围创建一个包装器。
然而,我最近发现的是Moles project。从主页; “Moles允许用委托替换任何.NET方法.Moles支持静态或非虚拟方法。”它可能对您目前的情况有用。
答案 3 :(得分:2)
到目前为止,我发现的最佳解决方案是Telerik的JustMock - 不幸的是,只有付费的版本允许模拟静态。
虽然包装静力学的想法很好 - 但你不能总是这样做。如果你想测试一些使用某些静态类的代码,那么就不可能总是切换出来并使用包装器。在这种情况下,JustMock看起来是一个合理的解决方案,我可能会在不久的将来在某些解决方案中使用它。
答案 4 :(得分:1)
您可以使用Microsoft Fakes。它肯定会解决这个问题。 请参阅 https://msdn.microsoft.com/en-us/library/hh549175.aspx
答案 5 :(得分:0)
使用@Sujith建议的Microsoft Fakes是可行的解决方案。这是您实际的操作方式:
System.Web
,然后右键单击System.Web.4.0.0.0.Fakes
使用以下代码:
使用(Microsoft.QualityTools.Testing.Fakes.ShimsContext.Create()) { System.Web.Fakes.ShimHttpRuntime.AppDomainAppVirtualPathGet =()=>“ /”; //做任何需要伪造的AppDomainAppVirtualPath }