使用最小起订量模拟静态属性
Posted
技术标签:
【中文标题】使用最小起订量模拟静态属性【英文标题】:Mock static property with moq 【发布时间】:2011-01-25 20:37:34 【问题描述】:我对使用moq 还是很陌生。我正在为HttpModule
创建一些单元测试用例,一切正常,直到我点击static
属性,如下所示
this.applicationPath = (HttpRuntime.AppDomainAppVirtualPath.Length > 1) ? HttpRuntime.AppDomainAppVirtualPath : String.Empty;
我不知道如何为static
类和属性创建模拟,例如HttpRuntime.AppDomainAppVirtualPath
。 context
、request
和 response
已经用我从 moq 获得的示例代码很好地模拟了。如果有人可以帮助我,我将不胜感激。
【问题讨论】:
【参考方案1】: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 工作
【讨论】:
在询问起订量时,建议商业产品有点过时。 为什么?这是一个选择。包装静态更好,但知道你的选择总是一件好事。 他正在寻求有关如何使用 Moq 执行此操作的解决方案。这就是为什么。 不,它似乎没有被替换为 HttpRuntime.AppDomainAppVirtualPath。测试在此调用时崩溃。有输入吗? +1 在 TypeMock 工作并参与社区活动 :)【参考方案2】: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
。
然后是起订量:
var staticMock = new Mock<IStatic>();
staticMock.Setup(s => s.ReturnOne()).Returns(2);
【讨论】:
@Yasser 你破坏了代码示例,我正在恢复你的更改。【参考方案3】:如前面的答案所述,您不能在静态方法上使用 MoQ,如果需要,最好的办法是围绕静态类创建一个包装器。
不过,我最近发现了Moles project。从主页; “Moles 允许用委托替换任何 .NET 方法。Moles 支持静态或非虚拟方法。”它可能对您当前的情况有用。
【讨论】:
有趣,会去看看。 不要使用鼹鼠。首先,它增加了很多麻烦并显着减慢了构建时间。其次,由于这条评论最初是由微软更新的模拟框架发布的,因此它已被取代。第三,它与 VS2012(使用较新的框架)不兼容,这在工作中很头疼,因为我们这里有很多用 Moles 编写的测试,需要在升级之前去 Molesified。模拟静态方法很诱人(尤其是遗留代码),但如果可以的话,IMO 最好只编写代码以对单元测试更友好。 当然可以,但是问题涉及我们大多数人无法修改的 HttpRuntime 类,在这种情况下,不可避免地需要以某种方式模拟静态方法/属性。【参考方案4】:到目前为止,我发现的最佳解决方案是 Telerik 的 JustMock - 不幸的是,只有付费版本才允许模拟静态。
虽然包装静态的想法是一个很好的想法 - 你不能总是这样做。如果您想测试一些已经使用了一些静态类的代码,那么并不总是可以切换并使用包装器。在这种情况下,JustMock 看起来是一个合理的解决方案,我可能会在不久的将来将它用于一些解决方案。
【讨论】:
【参考方案5】:您可以为此使用 Microsoft Fakes。它肯定会解决问题。 参考https://msdn.microsoft.com/en-us/library/hh549175.aspx
【讨论】:
虽然此链接可能会回答问题,但最好也在问题中说明重要细节(链接可能会失效)。【参考方案6】:按照@Sujith 的建议使用Microsoft Fakes 是一个可行的解决方案。以下是你的实际操作方式:
在您的测试项目参考中找到System.Web
并右键单击
选择“添加”。这增加了参考System.Web.4.0.0.0.Fakes
使用以下代码:
使用 (Microsoft.QualityTools.Testing.Fakes.ShimsContext.Create()) System.Web.Fakes.ShimHttpRuntime.AppDomainAppVirtualPathGet = () => "/"; // 做任何需要伪造的 AppDomainAppVirtualPath 的事情
【讨论】:
以上是关于使用最小起订量模拟静态属性的主要内容,如果未能解决你的问题,请参考以下文章