【发布时间】:2009-07-02 17:10:15
【问题描述】:
我想在 Junit 测试用例中测试 Spring 配置,而不在配置的 bean 上调用 init-method。我本可以编写我的初始化方法来跳过基于系统属性的实际工作,这些系统属性可以在测试用例中设置,但我正在寻找一个更清洁的解决方案。
【问题讨论】:
我想在 Junit 测试用例中测试 Spring 配置,而不在配置的 bean 上调用 init-method。我本可以编写我的初始化方法来跳过基于系统属性的实际工作,这些系统属性可以在测试用例中设置,但我正在寻找一个更清洁的解决方案。
【问题讨论】:
您的 JUnit 测试是否使用相同的 Spring 上下文配置文件?我猜答案是肯定的......如果您的测试使用备用弹簧配置,它将简化问题。
我使用过的最简洁的方法之一是使用一些方便的注释,如下所示:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class MovieServiceTest {
// ...
}
Spring 将其称为“TestContext 框架”,JUnit 测试将寻找一个上下文配置文件,在上面的示例中,名称为“MovieServiceTest-context.xml”
然后您可以在没有 init 方法的情况下定义 bean。虽然……你也不想测试一下吗?
【讨论】:
这是Spring的配置XML中bean的属性init-method指定的init方法吗?如果是这样,您能否使用与生产环境不同的上下文 XML 来运行测试来实现这一点?
【讨论】:
您可以稍微老派一点,扩展正在测试的类并覆盖 init 方法。
或者你可以稍微重构一下,注入一个 init 方法使用的 init 策略对象。
虽然我更喜欢 testContext.xml 方式...
【讨论】:
决定回答我自己的问题以分享找到的解决方案。不喜欢在没有初始化方法的情况下维护配置文件的另一个副本的解决方案。我的解决方案并不完美,但可以完成工作。
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();
}
【讨论】:
这是单元测试还是集成测试?如果是单元测试,那么你不应该加载上下文,因此你不需要担心 init 方法。如果是集成测试,我指的是任何验证几个类之间交互的测试,那么你需要确保确实调用了 init 方法以确保测试有效。
尽管如此,前面的章节一针见血,使用了不调用 init 方法的不同上下文。
【讨论】: