5

我有一个带有受保护的 @PostConstruct 方法的静态 Spring 3.2.4 bean,该方法在初始化时从数据库加载数据。

创建 jUnit 测试时,在我的测试方法中,我想设置数据库中的数据以适当地测试 bean。但是,鉴于 bean 在我的测试方法之前实例化,我不知道如何请求 Spring 将 bean 的实例化推迟到方法完成。

鉴于 @PostConstruct 方法受到保护,我不能直接调用它来重新初始化 bean,除非我使用反射。

还有另一种方法可以做到这一点,还是反射是唯一的方法?Spring 是否有任何 Util 类使其更容易,还是我必须使用标准的 java 反射?

4

1 回答 1

2

对于此类用例,您始终可以以编程方式启动上下文。请注意,在这种情况下,您负责上下文的生命周期。下面的伪代码说明了这一点:

@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();
        }
    }
}

如果这成为一个经常出现的用例,您可以创建一个模板方法来启动容器并调用回调接口。这样您就可以在一个中心位置共享上下文生命周期管理。

于 2014-03-13T10:31:22.093 回答