如何推迟调用@PostConstruct,直到jUnit设置测试上下文
Posted
技术标签:
【中文标题】如何推迟调用@PostConstruct,直到jUnit设置测试上下文【英文标题】:How to defer calling @PostConstruct until jUnit has setup test context 【发布时间】:2013-10-18 03:29:58 【问题描述】:我有一个带有受保护的 @PostConstruct 方法的静态 Spring 3.2.4 bean,该方法在初始化时从数据库加载数据。
在创建 jUnit 测试时,在我的测试方法中,我想设置数据库中的数据以适当地测试 bean。但是,鉴于 bean 在我的测试方法之前实例化,我不知道如何请求 Spring 将 bean 的实例化推迟到方法完成。
鉴于@PostConstruct 方法是受保护的,我不能直接调用它来重新初始化bean,除非我使用反射。
还有其他方法可以做到这一点,还是反射是唯一的方法? Spring 是否有任何 Util 类使其更容易,还是我必须使用标准的 java 反射?
【问题讨论】:
【参考方案1】:您始终可以针对此类用例以编程方式启动上下文。请注意,在这种情况下,您负责上下文的生命周期。下面的伪代码说明了这一点:
@Test
public void yourTest()
// setup your database
ConfigurableApplicationContext context =
new ClassPathXmlApplicationContext("/org/foo/your-context.xml");
// Or new AnnotationConfigApplicationContext(YourConfig.class)
try
YourBean bean = context.getBean("beanId");
// Assertions
finally
context.close();
您可能需要 Spring 来初始化您的数据库。例如,您可以使用常规 Spring 测试上下文支持来仅初始化数据库设置所需的 bean,并以编程方式启动另一个上下文来断言您的服务。如果该上下文需要一些用于数据库初始化的服务,您可以启动一个子上下文,例如
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration // for instance FooTest-context.xml
public class FooTest
@Autowired
private ApplicationContext mainContext;
@Test
public void yourTest()
// setup your database
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext();
context.setParent(mainContext);
context.setConfigLocation("/org/foo/your-context.xml");
context.refresh();
try
YourBean bean = context.getBean("beanId");
// Assertions
finally
context.close();
如果这成为一个经常使用的用例,您可以创建一个模板方法来启动容器并调用回调接口。这样您就可以在一个中心位置共享上下文生命周期管理。
【讨论】:
谢谢。我最终解决了这个问题,但你的解决方案肯定给了我另一种看待它的方式。以上是关于如何推迟调用@PostConstruct,直到jUnit设置测试上下文的主要内容,如果未能解决你的问题,请参考以下文章
如何推迟加载 UpdatePanel 内容,直到页面呈现后?
Spring4-@PostConstruct和@PreDestroy注解的使用
Mockito + Spring + @PostConstruct,mock初始化错误,为啥会调用@PostConstruct?