对不同的测试方法使用不同的 Spring 测试上下文配置
Use different Spring test context configuration for different test methods
我们有一个基于 Spring 的 JUnit 测试 class,它正在利用内部测试上下文配置 class
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ServiceTest.Config.class)
public class ServiceTest {
@Test
public void someTest() {
...
@Configuration
@PropertySource(value = { "classpath:application.properties" })
@ComponentScan({ "..." })
public static class Config {
...
最近向服务 class 引入了新功能,为此应将相关测试添加到 ServiceTest。然而,这些还需要创建不同的测试上下文配置 class(现有配置 class 的内部结构相当复杂,更改它以服务于新旧测试似乎非常困难,如果完全可能)
有没有办法在一个测试中实现某些测试方法 class 使用一种配置 class 而其他方法使用另一种配置? @ContextConfiguration
似乎仅适用于 class 级别,因此解决方案可能是为新测试创建另一个测试 class,它将利用其自己的上下文配置 class;但这意味着相同的服务 class 正在通过两个不同的测试 classes
当我必须解决这个问题时,我会使用这些方法:
- 在设置方法中手动构建上下文,而不是使用注释。
- 将通用测试代码移动到基础class并扩展它。这允许我 运行 具有不同 spring 上下文的测试。
- 以上两者的混合。基 class 然后包含从片段构建 spring 上下文的方法(扩展可以覆盖)。这也允许我覆盖没有意义的测试用例或在某些测试中做额外的 pre/post 工作。
请记住,注释只能解决一般情况。当你离开共同点时,你将不得不复制他们的部分或全部工作。
根据 Aaron 关于手动构建上下文的建议,我找不到任何好的示例,所以在花了一些时间让它工作之后,我想我会 post 我使用的代码的简单版本以防万一帮助其他人:
class MyTest {
@Autowired
private SomeService service;
@Autowired
private ConfigurableApplicationContext applicationContext;
public void init(Class<?> testClass) throws Exception {
TestContextManager testContextManager = new TestContextManager(testClass);
testContextManager.prepareTestInstance(this);
}
@After
public void tearDown() throws Exception {
applicationContext.close();
}
@Test
public void test1() throws Exception {
init(ConfigATest.class);
service.doSomething();
// assert something
}
@Test
public void test2() throws Exception {
init(ConfigBTest.class);
service.doSomething();
// assert something
}
@ContextConfiguration(classes = {
ConfigATest.ConfigA.class
})
static class ConfigATest {
static class ConfigA {
@Bean
public SomeService someService() {
return new SomeService(new A());
}
}
}
@ContextConfiguration(classes = {
ConfigBTest.ConfigB.class
})
static class ConfigBTest {
static class ConfigB {
@Bean
public SomeService someService() {
return new SomeService(new B());
}
}
}
}
我们有一个基于 Spring 的 JUnit 测试 class,它正在利用内部测试上下文配置 class
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ServiceTest.Config.class)
public class ServiceTest {
@Test
public void someTest() {
...
@Configuration
@PropertySource(value = { "classpath:application.properties" })
@ComponentScan({ "..." })
public static class Config {
...
最近向服务 class 引入了新功能,为此应将相关测试添加到 ServiceTest。然而,这些还需要创建不同的测试上下文配置 class(现有配置 class 的内部结构相当复杂,更改它以服务于新旧测试似乎非常困难,如果完全可能)
有没有办法在一个测试中实现某些测试方法 class 使用一种配置 class 而其他方法使用另一种配置? @ContextConfiguration
似乎仅适用于 class 级别,因此解决方案可能是为新测试创建另一个测试 class,它将利用其自己的上下文配置 class;但这意味着相同的服务 class 正在通过两个不同的测试 classes
当我必须解决这个问题时,我会使用这些方法:
- 在设置方法中手动构建上下文,而不是使用注释。
- 将通用测试代码移动到基础class并扩展它。这允许我 运行 具有不同 spring 上下文的测试。
- 以上两者的混合。基 class 然后包含从片段构建 spring 上下文的方法(扩展可以覆盖)。这也允许我覆盖没有意义的测试用例或在某些测试中做额外的 pre/post 工作。
请记住,注释只能解决一般情况。当你离开共同点时,你将不得不复制他们的部分或全部工作。
根据 Aaron 关于手动构建上下文的建议,我找不到任何好的示例,所以在花了一些时间让它工作之后,我想我会 post 我使用的代码的简单版本以防万一帮助其他人:
class MyTest {
@Autowired
private SomeService service;
@Autowired
private ConfigurableApplicationContext applicationContext;
public void init(Class<?> testClass) throws Exception {
TestContextManager testContextManager = new TestContextManager(testClass);
testContextManager.prepareTestInstance(this);
}
@After
public void tearDown() throws Exception {
applicationContext.close();
}
@Test
public void test1() throws Exception {
init(ConfigATest.class);
service.doSomething();
// assert something
}
@Test
public void test2() throws Exception {
init(ConfigBTest.class);
service.doSomething();
// assert something
}
@ContextConfiguration(classes = {
ConfigATest.ConfigA.class
})
static class ConfigATest {
static class ConfigA {
@Bean
public SomeService someService() {
return new SomeService(new A());
}
}
}
@ContextConfiguration(classes = {
ConfigBTest.ConfigB.class
})
static class ConfigBTest {
static class ConfigB {
@Bean
public SomeService someService() {
return new SomeService(new B());
}
}
}
}