【发布时间】:2010-12-06 22:00:03
【问题描述】:
我的 applicationContext-test.xml 中有一个 bean,用于模拟外部搜索引擎。这样,当我运行测试时,只要我的应用程序代码引用这个搜索引擎,我就知道我使用的是我的模拟引擎而不是真正的引擎。
我面临的一个问题是我希望这个引擎在不同的场景中表现不同。例如,当我调用getDocuments() 时,我通常希望它返回文档。但有时我希望它抛出异常以确保我的应用程序代码正确处理异常。
我可以通过在我的测试代码中引用 bean 并更改一些存根来实现这一点,但是我必须将存根改回原来的样子,这样我的其他测试也能通过。由于许多原因,这似乎是一种不好的做法,所以我正在寻找替代方法。
我考虑过的一种替代方法是完全重新初始化 bean。 bean 使用静态工厂方法从 applicationContext-test.xml 初始化。我想做的是:
- 从我的测试代码中引用 bean 来更改它的一些存根
- 使用这些新存根运行测试
- 在此测试结束时,使用 applicationContext-test.xml 中指定的静态工厂方法重新初始化 bean
我尝试过这样的事情:
ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(
new String[] { "applicationContext-test.xml" });
Factory factory = appContext.getBean(Factory.class);
factory = EngineMocks.createMockEngineFactory();
但这并不能解决问题。在此之后运行的任何测试仍然会失败。似乎我的新 factory 变量包含我想要的 Factory 并相应地运行,但是当在其他地方引用 bean 时,getDocuments() 仍然会抛出之前存根的异常。显然,我的重新初始化只影响了局部变量,而不影响 bean 本身。
谁能告诉我如何实现我的目标?
更新
虽然我很欣赏有关如何编写更好的测试和更好的模拟的建议,但我的目标是重新初始化 bean。我相信无论是否适合我的用例,学习如何做到这一点都是有价值的(我相信它确实适合我的用例,但我很难在这里说服我的一些批评者)。
唯一能让我投赞成票或绿色勾号的答案是那些建议我如何重新初始化我的 bean 的答案。
【问题讨论】:
-
我的回答会有点取决于您当前如何创建测试替身(例如模拟、存根)?它是手工制作的,还是您使用的是 easymock 或 mockito 之类的?
-
我的模拟是使用 Mockito 创建的,它们是通过 applicationContext 设置的。换句话说,我不会为我编写的每个测试制作模拟,而是我的应用程序代码引用了一个 @Resource,因此当我运行测试时,我加载我的应用程序上下文,以及引用的每一段应用程序代码该 bean 现在使用的是模拟版本而不是真实版本。
标签: java unit-testing spring-mvc dependency-injection mockito