简体   繁体   English

使用moq模拟静态属性

[英]Mock static property with moq

I am pretty new to use moq . 我很擅长使用moq I am into creating some unit test case to HttpModule and everything works fine until I hit a static property as follows 我正在为HttpModule创建一些单元测试用例,一切正常,直到我点击static属性,如下所示

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

I do not know how create mocks for static class and property like HttpRuntime.AppDomainAppVirtualPath . 我不知道如何为static类和属性创建模拟,如HttpRuntime.AppDomainAppVirtualPath The context , request and response have been mocked well with sample code I get from moq. 我从moq获得的示例代码很好地模拟了contextrequestresponse I will appreciate if somebody can help me on this. 如果有人可以帮助我,我将不胜感激。

Moq can't fake static members. Moq无法伪造静态成员。

As a solution you can create a wrapper class (Adapter Pattern) holding the static property and fake its members. 作为一种解决方案,您可以创建一个包含静态属性的包装类(适配器模式)并伪造其成员。
For example: 例如:

public class HttpRuntimeWrapper
{
    public virtual string AppDomainAppVirtualPath 
    { 
        get
        { 
            return HttpRuntime.AppDomainAppVirtualPath; 
        }
    }
}

In the production code you can access this class instead of HttpRuntime and fake this property: 在生产代码中,您可以访问此类而不是HttpRuntime并伪造此属性:

[Test]
public void AppDomainAppVirtualPathTest()
{
    var mock = new Moq.Mock<HttpRuntimeWrapper>();
    mock.Setup(fake => fake.AppDomainAppVirtualPath).Returns("FakedPath");

    Assert.AreEqual("FakedPath", mock.Object.AppDomainAppVirtualPath);
}

Another solution is to use Isolation framework (as Typemock Isolator ) in which you can fake static classes and members. 另一种解决方案是使用隔离框架(作为Typemock隔离器 ),您可以在其中伪造静态类和成员。
For example: 例如:

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

Disclaimer - I work at Typemock 免责声明 - 我在Typemock工作

You cannot Moq static methods with Moq. 你不能用Moq的Moq静态方法。

This is not a bad thing in reality, static methods and classes do have their place but for logic they make unit testing difficult. 这在现实中并不坏,静态方法和类确实有它们的位置,但对于逻辑,它们使单元测试变得困难。 Naturally you'll run into them when using other libraries. 当然,在使用其他库时你会遇到它们。 To get around this you'll need to write an adapter (wrapper) around the static code, and provide an interface. 为了解决这个问题,你需要在静态代码周围编写一个适配器 (包装器),并提供一个接口。 For example: 例如:

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

Note, I've ommited the concrete class that uses IStatic for the production code. 注意,我已经省略了使用IStatic作为生产代码的具体类。 All it would be is a class which uses IStatic and your production code would make use of this class, rather than StaticClass above. 它只是一个使用IStatic的类,你的生产代码将使用这个类,而不是上面的StaticClass

Then with Moq: 然后用Moq:

var staticMock = new Mock<IStatic>();
staticMock.Setup(s => s.ReturnOne()).Returns(2);

As mentioned in previous answers, you can't use MoQ on static methods, and if you need to, your best shot is to create a wrapper around the static class. 如前面的答案所述,你不能在静态方法上使用MoQ,如果需要,最好的方法是在静态类周围创建一个包装器。

However, something I've discovered recently is the Moles project . 然而,我最近发现的是Moles项目 From the homepage; 从主页; "Moles allows to replace any .NET method with a delegate. Moles supports static or non-virtual methods." “Moles允许用委托替换任何.NET方法.Moles支持静态或非虚拟方法。” It might be useful for your current situation. 它可能对您目前的情况有用。

Best solution I have found so far is Telerik's JustMock - unfortunately only the paid for version allows mocking of statics. 到目前为止我找到的最佳解决方案是Telerik的JustMock - 不幸的是只有付费的版本允许模拟静态。

While the idea of wrapping statics is a good one - you can't always do this. 虽然包装静力学的想法很好 - 但你不能总是这样做。 If you want to test some code that uses some static classes already then it's not always possible to switch out and use a wrapper. 如果你想测试一些使用某些静态类的代码,那么就不可能总是切换出来并使用包装器。 In this case JustMock looks a reasonable solution and I'm probably going to use it on some solutions in the near future. 在这种情况下,JustMock看起来是一个合理的解决方案,我可能会在不久的将来在一些解决方案上使用它。

You can use Microsoft Fakes for this. 您可以使用Microsoft Fakes。 It will definitely solve the issue. 它肯定会解决这个问题。 Refer to https://msdn.microsoft.com/en-us/library/hh549175.aspx 请参阅https://msdn.microsoft.com/en-us/library/hh549175.aspx

Using Microsoft Fakes as suggested by @Sujith is a viable solution. 按照@Sujith的建议使用Microsoft Fakes是一个可行的解决方案。 Here is how you actually do it: 以下是您实际操作的方式:

  • Find System.Web in your reference of your test project and right click 在测试项目的参考中找到System.Web并右键单击
  • Choose "Add". 选择“添加”。 This adds reference System.Web.4.0.0.0.Fakes 这会添加参考System.Web.4.0.0.0.Fakes
  • Use following code: 使用以下代码:

    using (Microsoft.QualityTools.Testing.Fakes.ShimsContext.Create()) { System.Web.Fakes.ShimHttpRuntime.AppDomainAppVirtualPathGet = () => "/"; using(Microsoft.QualityTools.Testing.Fakes.ShimsContext.Create()){System.Web.Fakes.ShimHttpRuntime.AppDomainAppVirtualPathGet =()=>“/”; // Do what ever needs the faked AppDomainAppVirtualPath } //做什么都需要伪造的AppDomainAppVirtualPath}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM