首页 文章

使用moq模拟静态属性

提问于
浏览
41

我很新用moq . 我正在为 HttpModule 创建一些单元测试用例,一切正常,直到我点击 static 属性,如下所示

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

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

5 回答

  • 59

    到目前为止我找到的最佳解决方案是Telerik的JustMock - 遗憾的是只有付费的版本允许模拟静态 .

    虽然包装静力学的想法很好 - 但你不能总是这样做 . 如果你想测试一些使用某些静态类的代码,那么就不可能总是切换出来并使用包装器 . 在这种情况下,JustMock看起来是一个合理的解决方案,我可能会在不久的将来在一些解决方案上使用它 .

  • 2

    您可以使用Microsoft Fakes . 它肯定会解决这个问题 . 参考 https://msdn.microsoft.com/en-us/library/hh549175.aspx

  • 11

    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

    你不能用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);
    
  • 3

    如前面的答案所述,你不能在静态方法上使用MoQ,如果需要,最好的方法是在静态类周围创建一个包装器 .

    但是,我最近发现的是Moles project . 从主页; "Moles allows to replace any .NET method with a delegate. Moles supports static or non-virtual methods."这可能对您目前的情况有用 .

相关问题