你如何嘲笑一个密封课?

嘲笑封闭式课程可能会非常痛苦。 我目前喜欢一个适配器模式来处理这个问题,但一些关于只是保持感觉怪异。

那么,嘲笑密封课程的最好方法是什么?

Java的答案是值得欢迎的 。 事实上,我预计Java社区已经处理了更长的时间,并且提供了很多东西。

但是这里有一些.NET的意见:

  • 为什么鸭子键入问题的C#开发人员
  • 创build密封和其他types的包装嘲笑
  • WCF(和Moq)的unit testing

我一般的经验法则是我需要模拟的对象也应该有一个共同的接口。 我认为这是正确的devise,使testing更容易(通常是如果你做TDD的话)。 有关这方面的更多信息,请参阅Googletesting博客最新文章 (请参阅第9点)。

另外,在过去的四年中,我一直以Java为主,可以说我一方面可以指望创build最终(密封)课程的次数。 另一个规则是我应该总是有一个很好的理由来封闭一个class级,而不是默认封闭class级。

对于.NET,你可以使用类似于TypeMock的东西,它使用分析API,并允许你调用几乎所有的东西。

我相信来自Microsoft Research的Moles允许你这样做。 从Moles页面:

痣可以用来绕开任何.NET方法,包括密封types的非虚拟/静态方法。

更新:在即将到来的VS 11版本中有一个叫做“Fakes”的新框架,用来取代Moles:

Visual Studio 11中的Fakes Framework是Moles&Stub的下一代,最终将取而代之。 假货不同于痣,但是,从痣到假货需要对代码进行一些修改。 此迁移指南将在稍后提供。

要求 :Visual Studio 11 Ultimate,.NET 4.5

TypeMock的问题是它借口糟糕的devise。 现在,我知道隐藏它通常是别人不好的devise,但允许它进入你的开发过程可以很容易地导致你自己的坏devise。

我想如果你打算使用一个模拟框架,你应该使用一个传统的框架(如Moq),并围绕unmockable事物创build一个隔离层,然后模拟隔离层。

我几乎总是避免在我的代码中深入依赖外部类。 相反,我宁愿使用适配器/网桥来与他们交谈。 那样,我正在处理我的语义,翻译的痛苦是孤立在一个类。

这也使得从长远来看更容易切换我的依赖关系。

有没有办法从接口实现一个密封的类…并嘲笑接口呢?

在我的某些事物中,认为封闭课程是错误的,但这只是我:)

我通常采取创build一个接口和适配器/代理类的方式来方便模拟密封types。 但是,我也尝试过跳过接口的创build,并使代理types不被虚拟方法密封。 当代理真的是封装和使用密封类的一部分的自然基类时,这很有效。

当处理需要这种适配的代码时,我厌倦了执行相同的操作来创build接口和代理types,所以我实现了一个库来自动执行任务。

代码比你引用的文章中给出的示例稍微复杂一些,因为它产生一个程序集(而不是源代码),允许在任何types上执行代码生成,并且不需要那么多的configuration。

欲了解更多信息,请参阅此页面 。

嘲笑一个封闭的类是完全合理的,因为许多框架类是封闭的。

在我的情况下,我试图嘲笑.Net的MessageQueue类,以便我可以TDD我优雅的exception处理逻辑。

如果有人有关于如何克服Moq关于“无法覆盖的成员上的无效设置”的错误的想法,请让我知道。

码:

  [TestMethod] public void Test() { Queue<Message> messages = new Queue<Message>(); Action<Message> sendDelegate = msg => messages.Enqueue(msg); Func<TimeSpan, MessageQueueTransaction, Message> receiveDelegate = (v1, v2) => { throw new Exception("Test Exception to simulate a failed queue read."); }; MessageQueue mockQueue = QueueMonitorHelper.MockQueue(sendDelegate, receiveDelegate).Object; } public static Mock<MessageQueue> MockQueue (Action<Message> sendDelegate, Func<TimeSpan, MessageQueueTransaction, Message> receiveDelegate) { Mock<MessageQueue> mockQueue = new Mock<MessageQueue>(MockBehavior.Strict); Expression<Action<MessageQueue>> sendMock = (msmq) => msmq.Send(It.IsAny<Message>()); //message => messages.Enqueue(message); mockQueue.Setup(sendMock).Callback<Message>(sendDelegate); Expression<Func<MessageQueue, Message>> receiveMock = (msmq) => msmq.Receive(It.IsAny<TimeSpan>(), It.IsAny<MessageQueueTransaction>()); mockQueue.Setup(receiveMock).Returns<TimeSpan, MessageQueueTransaction>(receiveDelegate); return mockQueue; } 

我最近遇到这个问题,在阅读/search网页后,似乎没有简单的方法,除了使用上述的其他工具。 或者像我一样处理事情的原油:

  • 创build密封类的实例,而不必调用构造函数。
  • System.Runtime.Serialization.FormatterServices.GetUninitializedObject(instanceType);

  • 通过reflection将值分配给您的属性/字段

  • YourObject.GetType()。GetProperty(“PropertyName”)。SetValue(dto,newValue,null);
  • YourObject.GetType()。GetField(“FieldName”)。SetValue(dto,newValue);

虽然目前只有beta版本,但我认为值得牢记新的Fakes框架 ( Visual Studio 11 Beta版本的一部分)的Shim特性。

Shimtypes提供了一种将.NET方法绕到用户定义委托的机制。 Shimtypes由Fakes生成器代码生成,并使用我们称之为Shimtypes的委托来指定新的方法实现。 在引擎盖下,填充types使用在方法MSIL体中运行时注入的callback函数。

就我个人而言,我正在研究如何使用它来模拟密封框架类(如DrawingContext)上的方法。