【问题标题】:C# Factory pattern with Abstract and Internal Constructor, under Unit test单元测试中具有抽象和内部构造函数的 C# 工厂模式
【发布时间】:2014-04-25 10:13:01
【问题描述】:

在我心中是Microsoft.ServiceBus QueueClient

所以QueueClient 是抽象类,带有一个内部构造函数;我们调用QueueClient.CreateFromConnectionString(...) 来获取AMQP 或SBMP 具体客户端类。这是获取QueueClient 实例的唯一方法。

鉴于ConnectionString 指定了很多细节,我可以理解他们为什么使用这种模式。

但是在单元测试下,这个QueueClient很难mock,(至少Moq做不到);即使使用 Microsoft Fakes,ShimQueueClient 也只是一个包装器,其中包含一些您可以设置的方法,但您不能新建它或将其作为参数传递给下游。

我的问题是,当您出于某种原因决定使用这种 Pattern 时,您可以做些什么来使其对测试更友好?

我能想到的东西,比如你可以有一个静态方法让你QueueClient.CreateForTest(),但对此感到很奇怪;或者将这个QueueClient.CreateFromConnectionString 设置为虚拟字符串(我已经通过给它一个非常短的“正确”字符串来做到这一点,你可以在 IntelliTrace 中看到一些捕获的异常的成本)。

(注意:我并不是真的要求创建自己的IQueueClient 等)

非常感谢。

【问题讨论】:

    标签: c# unit-testing abstract-class factory-pattern internal


    【解决方案1】:

    我建议您创建一个基本接口来支持这种模式。您的带有内部构造函数的抽象类将实现此接口,使其能够灵活地进行伪造、摸清和替换。

    对于Microsoft.ServiceBus QueueClient,我会在生产代码中使用我自己的接口实现decorate,这样我就可以在单元测试中伪造装饰器。

    【讨论】:

    • 在 QueueClient 的情况下,它的签名是这样的:public abstract class QueueClient : MessageClientEntity, IMessageSessionEntity, IMessageSender, IMessageReceiver, IMessageBrowser 你的意思是你应该有一个包含所有这些的 IQueueClient 然后你做QueueClient : IQueueClient?也想知道这是否也是一个好的模式。
    • @Xied 对这两个问题都是肯定的。请参阅 IList。 public interface IList : ICollection, IEnumerable。允许在需要实现ICollection IEnumerable 的对象时使用IList
    • 顺便说一句,我们不能从 QueueClient 继承,因为它的两个方法是 internal abstract
    • @Xied 你需要使用装饰器或适配器模式装饰 QueueClient
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多