用moq模拟静态属性

我很新使用MOQ 。 我正在创build一些unit testing用例到HttpModule ,一切正常,直到我按照如下命中一个static属性

 this.applicationPath = (HttpRuntime.AppDomainAppVirtualPath.Length > 1) ? HttpRuntime.AppDomainAppVirtualPath : String.Empty; 

我不知道如何创build像HttpRuntime.AppDomainAppVirtualPath static类和属性的HttpRuntime.AppDomainAppVirtualPathcontextrequestresponse已经被我从moq获得的示例代码模拟得很好。 如果有人能帮助我,我将不胜感激。

Moq不能伪造静态成员。

作为一种解决scheme,您可以创build一个包装类(适配器模式),其中包含静态属性并伪造其成员。
例如:

 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); } 

另一种解决scheme是使用隔离框架(作为Typemock隔离器 ),在其中您可以伪造静态类和成员。
例如:

 Isolate.WhenCalled(() => HttpRuntime.AppDomainAppVirtualPath) .WillReturn("FakedPath"); 

免责声明 – 我在Typemock工作

Moq不能用Moq静态方法。

实际上这不是一件坏事,静态的方法和类都有它们的位置,但是逻辑上它们使unit testing变得困难。 当然,使用其他库时,你会碰到它们。 为了解决这个问题,你需要在静态代码周围写一个适配器 (wrapper),并提供一个接口。 例如:

 // 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); 

正如在前面的答案中提到的,你不能在静态方法上使用MoQ,如果你需要的话,最好的办法是在静态类中创build一个包装器。

不过,我最近发现的是Moles项目 。 从主页 “Moles允许使用委托来replace任何.NET方法,Moles支持静态或非虚拟方法。 这可能对你目前的情况有用。

我发现迄今为止最好的解决scheme是Telerik的JustMock – 不幸的是,只有付费版本允许模拟静态。

虽然包装静态的想法是一个好主意 – 你不能总是这样做。 如果你想testing一些使用了一些静态类的代码,那么就不一定总是可以使用一个包装器了。 在这种情况下,JustMock看起来是一个合理的解决scheme,我可能会在不久的将来在一些解决scheme上使用它。

你可以使用微软的假货。 这一定会解决问题。 请参阅https://msdn.microsoft.com/en-us/library/hh549175.aspx