2010-07-14 110 views
4

容器内测试通常与使用模拟对象进行测试相反。但是,由于模拟对象只是模仿真实对象的行为,因此容器内测试不是真正在真实环境中测试系统的唯一方法吗?容器内测试与模拟对象进行集成测试

作为容器内部测试和模拟对象的部分替代方案,Spring提供了TestContext框架,它可以很好地初始化Spring,而无需启动实际的应用程序容器(在我的情况下为Web应用程序服务器)。然而,这是有限的方法,因为它只初始化Spring特有的功能,而不支持应用程序服务器特定的功能。所以你不能测试一切。另外,因为它与用于真正web执行的默认WebApplicationContext不是100%相同,所以这种方法有点不合理吗?它不好吗?

对于容器内测试,至少有Cactus(过时),Jeeunit(一个非常小的项目)和JBoss Arquillian(仍然是α,但看起来很有希望)。我没有看到任何这些项目被广泛使用,那么容器内测试有什么不好的地方?容器内测试经常提到的主要缺点是执行速度慢。但是,当在持续集成环境中运行并且在相对较小的项目中运行时,这应该不成问题。

总结:我们应该进行容器内外测试还是为什么?使用模拟对象或替代初始化机制(如在Spring TestContext中)来进行集成测试会感觉不好吗?

附注:我最近问了一下categorization of integration test,这可能是相关的。

回答

3

但是,由于模拟对象只是模拟真实对象的行为,而不是容器内测试真正在真实环境中测试系统的唯一方法吗?

我认为简单的答案是肯定的,但是......我认为你的“整合测试分类”问题是非常相关的。单位和集成测试均为虽然服务功能不同,但重要。

单元测试与代码密切相关,如果启动和运行速度非常快,开发人员应该经常运行代码,并且通常会使用mock来实现高度的代码。这个想法是测试有问题的代码,而不是它的依赖或集成点。将单元测试全部放在容器中的问题是,它们运行得不那么频繁,否则会浪费太多开发时间。

我们已经在另一个项目中的其他项目的其他地方隔离了我们的容器内/集成测试,并且依赖于代码项目。它们旨在尽可能地模仿生产配置。这些测试需要更长的时间进行设置,运行时间更长,并且更有用于像cruisecontrol这样的运行。它们是手工操作的,特别是当我们在发布时或者在开发稳定之后。当我要去吃午餐或开会时,通常我会启动集成测试。当一个集成测试发现一个bug时,我们尝试编写一个单元测试,这个单元测试也演示了这个嘲讽的错误 - 这往往很难并且是不可能的。

我们通常会在单元测试中进行一些小的容器内测试,以确保弹簧接线正常工作或测试一些基本功能,但其他集成测试在另一个项目中完成。

所有这一切说,两者之间并没有明显的差别。有时我们会移动处理大量数据的单元测试,并花费很长时间进行集成测试,有时集成测试运行得足够快,并且足够有价值,可与代码一起使用。

+0

我非常好地运行了容器外的单元测试。其实,我不明白你为什么要运行“几个小容器内单元测试”来测试“弹簧布线”和东西?也许你在那里弄错了,你的意思是“一对小容器内集成测试*”吗?另外,我的理解是否正确:如果对运行时配置进行更改,则必须将该设置复制到集成测试项目中?您如何实际运行/初始化容器内测试?在某种框架的帮助下可能? – 2010-07-14 13:13:59

+0

我编辑了该部分。我的意思是我们在我们的单元测试集合中进行了几次集成测试,以确保所有的Spring接线都能正常工作。所有配置文件都带有代码 - 我们不会将任何配置复制到集成项目中。集成项目与生产代码共享相同的包路径,因此可以加载所有相同的src/main/resource(我们使用mvn)configs。 – Gray 2010-07-14 13:33:00

2

我想说我们应该做在容器内和外容器测试。我在测试容器时发现的主要问题是自动化所有内容的工作量更大。您可以通过Spring的集成测试支持获得一些更便宜的胜利,但我们不应该欺骗自己,因为这涵盖了部署容器中测试的所有内容。我发现他们可以在Spring集成测试中扮演一个角色,但我更倾向于使用虚假/存根服务和罐头结果来进行集成和容器内测试(这是我的“ d呼叫系统测试)。

如果您不确定嘲笑与st what之间的区别是什么,请查看Martin Fowler article

+0

你在容器内测试中使用了什么库?让我想到的是,每个容器内测试框架(Cactus,jeeunit,Arquillian)似乎都为不同的技术(如CDI,EJB,Servlet等)提供了特定的支持。难怪支持所有这些需要一些额外的配置: /感谢这篇文章的指针,我不得不承认,我在这种情况下经验很少。 – 2010-07-14 13:25:46