Java 如何重新初始化我的bean
我的applicationContext-test.xml中有一个bean,用于模拟外部搜索引擎。这样,当我运行测试时,每当我的应用程序代码引用这个搜索引擎时,我就知道我使用的是模拟引擎而不是真正的引擎 我面临的一个问题是,我希望这个引擎在不同的场景中表现不同。例如,当我调用Java 如何重新初始化我的bean,java,unit-testing,spring-mvc,dependency-injection,mockito,Java,Unit Testing,Spring Mvc,Dependency Injection,Mockito,我的applicationContext-test.xml中有一个bean,用于模拟外部搜索引擎。这样,当我运行测试时,每当我的应用程序代码引用这个搜索引擎时,我就知道我使用的是模拟引擎而不是真正的引擎 我面临的一个问题是,我希望这个引擎在不同的场景中表现不同。例如,当我调用getDocuments()时,我通常希望它返回文档。但有时我希望它抛出一个异常,以确保我的应用程序代码正确地处理该异常 我可以通过在测试代码中引用bean并更改一些存根来实现这一点,但随后我必须将存根更改回原来的状态,以便
getDocuments()
时,我通常希望它返回文档。但有时我希望它抛出一个异常,以确保我的应用程序代码正确地处理该异常
我可以通过在测试代码中引用bean并更改一些存根来实现这一点,但随后我必须将存根更改回原来的状态,以便我的其他测试也能通过。出于许多原因,这似乎是一种不好的做法,所以我正在寻找替代方案
我考虑的一个替代方案是完全重新初始化bean。bean是通过一个静态工厂方法从applicationContext-test.xml初始化的。我想做的是:
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的答案 您应该定义需要结果时的案例和需要异常时的案例。它们应该通过方法的输入参数来区分。否则,这不是一个好的测试。因此,对于给定的一组参数,输出应该是可预测的。如何注入搜索引擎的不同实现?只需创建更多表示搜索引擎不同模拟的bean
- 一个测试类用一个mock初始化,另一个测试类用另一个mock初始化;当然,这意味着您将为正在测试的特定类拥有更多的测试类(不是很好/干净)
- 在一个测试类中注入更多模拟(搜索引擎)。一些测试方法(来自该测试类)使用一个mock,其他测试方法使用另一个mock
- 而不是:
factory = EngineMocks.createMockEngineFactory();
做:
另外,如果您使用的是Spring集成测试,请确保使用@DirtiesContext注释您的方法,这样它就不会影响下一次测试。我不确定您的意思。这确实是两个不同的测试用例,但它们调用的应用程序代码对我的工厂使用相同的bean定义。我不希望通过一长串setter手动注入这个bean。在我看来,他是说您应该能够提供导致抛出异常的输入,而不是使用存根。@ahungerart:这没有多大意义。这个搜索引擎是一个外部jar。我不能改变它的工作方式。我无法将任何值传递到getDocuments()中,这些值会导致它抛出异常,因此,将特定值传递到模拟中以导致这种行为是没有意义的,是吗?@Samo-如果无法预测异常,那么您如何期望异常?很抱歉,我看不到全部情况。重点不是模拟导致异常的场景。关键是要确保异常得到正确处理。如果我的引擎抛出异常,我希望确保调用此引擎的服务将其吃掉并返回空列表。所以我只想引起例外,我不在乎如何。如果我在测试另一个层,我可以将参数传递到getDocumentsRange(int,int),这将导致异常。但是我正在测试引擎上面的一层,以确保它能够接受异常,因此我无法控制哪些参数被传递到方法中。@Belun:您的第二个建议不起作用,因为引用我的bean的代码是应用程序代码,而不是测试代码。测试负责加载定义这个bean的上下文。只有当我有多个测试应用程序上下文时,您的第一个建议才可能。即使我这样做了,这听起来像是糟糕的做法,我也无法运行我的其他测试,因为它们将使用引发异常的bean。正如你所建议的,我必须为这些测试设置多个测试类。@Samo:听起来有些不对劲。到目前为止,我看到了搜索引擎的三个bean和两个应用程序XML。真正的实现是一个,位于用于生产的应用程序xml中。其他2个bean是一个返回一些固定值(存根)的bean和一个在特定情况下抛出一些异常的bean;最后两个都在第二个应用程序xml中(用于测试)。我的图片怎么了?@Belun:你的图片怎么了?一段应用程序代码不能引用同一上下文中的两个不同bean。正如我所说,我的bean不是从测试代码加载的,而是在应用程序代码中引用的。例如,我的测试调用类A。类A从应用程序上下文引用BeanX。我没有设定者来改变这个豆子
factory.callMethodThatChangesTheStateOfThisObjectSuchThatItIsSuitableForYourTest(withOptionalParameters);