【问题标题】:Spring - Skip init-method in unit testSpring - 在单元测试中跳过初始化方法
【发布时间】:2009-07-02 17:10:15
【问题描述】:

我想在 Junit 测试用例中测试 Spring 配置,而不在配置的 bean 上调用 init-method。我本可以编写我的初始化方法来跳过基于系统属性的实际工作,这些系统属性可以在测试用例中设置,但我正在寻找一个更清洁的解决方案。

【问题讨论】:

    标签: java spring


    【解决方案1】:

    您的 JUnit 测试是否使用相同的 Spring 上下文配置文件?我猜答案是肯定的......如果您的测试使用备用弹簧配置,它将简化问题。

    我使用过的最简洁的方法之一是使用一些方便的注释,如下所示:

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration
    public class MovieServiceTest {
        // ...
    }
    

    Spring 将其称为“TestContext 框架”,JUnit 测试将寻找一个上下文配置文件,在上面的示例中,名称为“MovieServiceTest-context.xml”

    然后您可以在没有 init 方法的情况下定义 bean。虽然……你也不想测试一下吗?

    【讨论】:

    • 想到了这种方法,但它需要维护 2 个版本的 spring 配置。我的备份策略是在单元测试中从 prod 文件中删除所有“init-method”,然后手动加载应用程序上下文。如果找不到更好的解决方案,我可能会这样做。
    • 这是一个特别时髦的功能。我们开始坚持使用 junit3,但看起来 junit4 是要走的路。
    【解决方案2】:

    这是Spring的配置XML中bean的属性init-method指定的init方法吗?如果是这样,您能否使用与生产环境不同的上下文 XML 来运行测试来实现这一点?

    【讨论】:

      【解决方案3】:

      您可以稍微老派一点,扩展正在测试的类并覆盖 init 方法。

      或者你可以稍微重构一下,注入一个 init 方法使用的 init 策略对象。

      虽然我更喜欢 testContext.xml 方式...

      【讨论】:

        【解决方案4】:

        决定回答我自己的问题以分享找到的解决方案。不喜欢在没有初始化方法的情况下维护配置文件的另一个副本的解决方案。我的解决方案并不完美,但可以完成工作。

        public final static String INIT_METHOD_REGEX = "init-method=\"\\w+\"";
        public final static String DESTROY_METHOD_REGEX = "destroy-method=\"\\w+\"";
        public final static String PROPERTY_REGEX = "\\$\\{[^\\}]+\\}";
        
        private static List<List<String>> subs = new ArrayList<List<String>>();
        static {
            subs.add(Arrays.asList( new String[] { INIT_METHOD_REGEX, "" }));
            subs.add(Arrays.asList( new String[] { DESTROY_METHOD_REGEX, "" }));
            subs.add(Arrays.asList( new String[] { PROPERTY_REGEX, "" }));
        }
        
        static public void testSpringConfig(String configFile) throws IOException {
            URL springXml = Thread.currentThread().getContextClassLoader().getResource(configFile);
            InputStream is = springXml.openStream();
            byte[] buffer = new byte[8192];
            int readBytes;
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            while ((readBytes = is.read(buffer)) != -1)
                baos.write(buffer, 0, readBytes);
        
            String content = baos.toString();
            for (List<String> s : subs) 
                content = content.replaceAll(s.get(0), s.get(1));
        
            ByteArrayInputStream bais = new ByteArrayInputStream(content.getBytes());
            InputSource isrc = new InputSource(bais);
        
            GenericApplicationContext ctx = new GenericApplicationContext();
            XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ctx);
            xmlReader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_NONE);
            xmlReader.loadBeanDefinitions(isrc);
        
            ctx.refresh();
            ctx.start();
            ctx.close();
        }
        

        【讨论】:

          【解决方案5】:

          这是单元测试还是集成测试?如果是单元测试,那么你不应该加载上下文,因此你不需要担心 init 方法。如果是集成测试,我指的是任何验证几个类之间交互的测试,那么你需要确保确实调用了 init 方法以确保测试有效。

          尽管如此,前面的章节一针见血,使用了不调用 init 方法的不同上下文。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-03-21
            • 1970-01-01
            • 2022-08-03
            • 1970-01-01
            • 2011-07-22
            相关资源
            最近更新 更多