使用moq模拟静态属性

jyo*_*rge 42 c# asp.net unit-testing moq

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

this.applicationPath = (HttpRuntime.AppDomainAppVirtualPath.Length > 1) ? HttpRuntime.AppDomainAppVirtualPath : String.Empty;
Run Code Online (Sandbox Code Playgroud)

我不知道如何为static类和属性创建模拟HttpRuntime.AppDomainAppVirtualPath.的context,requestresponse已与示例代码我从起订量得到很好嘲笑.如果有人可以帮助我,我将不胜感激.

Eli*_*sha 61

Moq无法伪造静态成员.

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

public class HttpRuntimeWrapper
{
    public virtual string AppDomainAppVirtualPath 
    { 
        get
        { 
            return HttpRuntime.AppDomainAppVirtualPath; 
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在生产代码中,您可以访问此类而不是HttpRuntime伪造此属性:

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

    Assert.AreEqual("FakedPath", mock.Object.AppDomainAppVirtualPath);
}
Run Code Online (Sandbox Code Playgroud)

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

Isolate.WhenCalled(() => HttpRuntime.AppDomainAppVirtualPath)
       .WillReturn("FakedPath");
Run Code Online (Sandbox Code Playgroud)

免责声明 - 我在Typemock工作

  • 为什么?这是一个选择.包装静态更好,但了解您的选择总是一件好事. (37认同)
  • +1在TypeMock工作,并参与社区:) (12认同)
  • 在询问Moq时,建议使用可能的产品有点过时了. (5认同)
  • 他正在寻求有关如何使用Moq解决方案的解决方案.这就是为什么. (2认同)

Fin*_*las 12

你不能用Moq的Moq静态方法.

这在现实中并不坏,静态方法和类确实有它们的位置,但对于逻辑,它们使单元测试变得困难.当然,在使用其他库时你会遇到它们.为了解决这个问题,你需要在静态代码周围编写一个适配器(包装器),并提供一个接口.例如:

// 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();
}
Run Code Online (Sandbox Code Playgroud)

注意,我已经省略了使用IStatic作为生产代码的具体类.它只是一个使用IStatic的类,你的生产代码将使用这个类而不是StaticClass上面的类.

然后用Moq:

var staticMock = new Mock<IStatic>();
staticMock.Setup(s => s.ReturnOne()).Returns(2);
Run Code Online (Sandbox Code Playgroud)

  • @Yasser你打破了代码示例,我正在恢复你的改变. (2认同)