2008-12-15 42 views
5

我正在开发一个有很多外部服务消息的项目。仅以一种稍微“双曲线”的方式来描述它的一种好方法是系统必须将消息发送到Flicker API,Facebook API和Netflix API的应用程序。在测试之外使用模拟对象,不好的做法?

为了支持断开连接的场景,日志问题,开发人员可用性,配置等......我已经尝试过使用大量使用泛型和表达式树的方法。最终的结果是这样的:

Messenger<NetflixApi>.SendCustom(netflix => netflix.RecommendMovie("my message")); 

总的来说,我很高兴与最终结果,但觉得我犯了一个错误,或者忽视与问候测试和断开场景设计主要某处。

在测试过程中,无论是基于自动化,单元还是人为的,我已经实现了一个对象工厂,最初使用DI在“实时模式”下执行正确的操作,并使用Mocks提供一种无菌信使,在测试模式下,什么都做不了。

我只看到或读过关于纯粹TDD模式下使用的Mocks,而不是被用于某种愚蠢的对象。我所看到的方法将围绕存根或嘲讽所使用的所有API所依赖的HTTP通信功能。

我主要关心的是,我希望连接到的所有不同的服务,我最终将不得不做大量细粒度的工作来取代特定的HTTP实现,如果我使用存根方法,我会有3个类用于这些服务(IService,ConcreteService,StubService)以及在实现新方法或更改任何内容时维护这些服务都是真正的PITA。

在目前的实现中,我使用Mocks来免费获得“无菌模式”,几乎不必为了符合某个测试委托人而实施任何额外的任务。

问题是我错过了什么?我以更方便的方式违反了使用Mocks的设计负责人吗?

任何人都可以提供任何建议,如何从许多不同的外部服务中获得无菌模式,而无需跳过很多环节吗?

这个问题有意义吗?

感谢您的所有答案。

编辑#1:

我原来的问题并不清楚。任何null或mock对象都将纯粹用于开发/调试/测试环境。在生产中,发送这些消息的代码将是它们的实际实现。

我投票给每个人,因为似乎有很多不同的解决方案来解决这个问题,我会探索每一个。

请不要认为这个问题已经得到解答,我会尽我所能的赞赏。

回答

6

有一种名为Null Object的设计模式。空对象是一个实现接口的对象,所以它可以用在像你这样的场景中。

关于Null对象的重要之处在于,不要在可能破坏系统的地方返回null。

Null对象的目的是让一个虚拟和简单的东西的实现,就像一个模拟,但要在生产环境中使用。

最简单的例子是这样的:

class Logger{ 
private static ILogger _Logger; 

static Logger(){ 
    //DI injection here 
    _Logger = new NullLogger(); //or 
    _Logger = new TraceLogger(); 
} 
} 

interface ILogger{ 
void Log(string Message); 
} 

internal class TraceLogger:ILooger{ 
public void Log(string Message){ 
    //Code here 
} 
} 

internal class NullLogger{ 
public void Log(string Message){ 
    //Don't don anything, in purporse 
} 
} 

我希望这能帮助你

+0

第二次我看到这个线程的主题有一个红色的“空对象”警报继续... – abyx 2008-12-15 09:17:35

4

我想你可能需要澄清你的问题。 我不清楚你是否在测试中使用测试双打而没有存根或测试期望(所以用它们作为假货来满足所需的界面),或者你是否在谈论如何在生产场景中使用模拟来填充服务不可用(您的断开连接的情况)。

如果您在测试情况下谈论: 嘲笑是测试双打。测试使用假货而不是嘲笑或存根是没有问题的。如果你不需要在特定的测试中使用这个服务,它只是在那里提供一个给定的接口,即被测试的对象对它有依赖性,那就好了。这不是打破任何测试校长。

良好的嘲讽图书馆模糊了嘲笑,存根和假货之间的界限。

查看Martin Fowler关于不同类型测试双打的一些信息。 Mocks Aren't StubsTestDoubles

我真的很喜欢moq允许虚拟,假,存根和模拟对象之间的连续体的方式,而不需要跳过箍环来获取特定行为。 Check it out

如果你正在谈论在断开连接的场景中使用mock来生产......我会担心的。假的是要返回空对象或默认值为您所做的任何调用。这会将复杂性泄漏到所有使用这些服务的代码中(它们需要处理检查空返回值和空数组的操作)。我认为对于断开连接/无菌情况进行编码以处理依赖关系本身不可用,而不是接受它们的模拟实现并继续如同所有工作一样,将会更有意义。

4

这听起来像你对我可能想看看代理模式。即使与实际服务断开连接,您也希望像各种服务一样行事。因此,你的代码会更好地与代理交谈,而不是真实的交谈。然后,根据当前的连接状态,代理可以执行任何所需的操作。

相关问题