事先有一些小信息:
Spring Boot 1.3.0
Spring Mongo 1.3.3
Spring Security 3.1.4
Spring Security Cas 4.0.2
Flapdoodle Embedmongo 1.46.0
现在,我们有一个用
注释的抽象测试类 @RunWith(SpringJUnit4ClassRunner.class)
,@SpringApplicationConfiguration(TestConfig.class)
和@WebAppConfiguration
。
TestConfig类看起来像这样:
@Configuration
@EnableAutoConfiguration(exclude = { EmbeddedMongoAutoConfiguration.class })
@ComponentScan(value = { "package1", "package2" })
public class TestConfig {
}
如您所见,它会扫描这两个包中的所有内容,并同时提取其他几个配置类:
@Configuration
// needed if working with Spring-Data-Repository interfaces and subprojects
// http://stackoverflow.com/questions/29084824/spring-repository-components-not-found-in-gradle-subproject-springboot
@EnableMongoRepositories({ "package2.subpackage" })
public class ModelConfiguration {
}
和
@Configuration
@EnableAutoConfiguration(exclude = { EmbeddedMongoAutoConfiguration.class })
@EnableMongoRepositories(basePackages = { "package2" })
public class TestMongoConfiguration {
private static final String DESTROY_METHOD_CLOSE = "close";
private static final String DESTROY_METHOD_STOP = "stop";
private static final MongodStarter STARTER = MongodStarter.getDefaultInstance();
@Autowired
private MongoProperties mongoProperties;
@Autowired(required = false)
private MongoClientOptions mongoClientOptions;
@Autowired
private Environment environment;
@Bean(destroyMethod = DESTROY_METHOD_CLOSE)
public MongoClient mongo() throws IOException {
Net net = mongodProcess().getConfig().net();
mongoProperties.setHost(net.getServerAddress().getHostName());
mongoProperties.setPort(net.getPort());
return mongoProperties.createMongoClient(this.mongoClientOptions, environment);
}
@Bean(destroyMethod = DESTROY_METHOD_STOP)
public MongodProcess mongodProcess() throws IOException {
return mongodExecutable().start();
}
@Bean(destroyMethod = DESTROY_METHOD_STOP)
public MongodExecutable mongodExecutable() throws IOException {
return STARTER.prepare(mongodConfig());
}
@Bean
public IMongodConfig mongodConfig() throws IOException {
return new MongodConfigBuilder().version(Version.Main.PRODUCTION).build();
}
}
这是我的测试课程的一部分:
@SpringApplicationConfiguration(classes = TestClass.TestConfiguration.class)
public class TestClass extends AbstractTest {
@Order(Ordered.HIGHEST_PRECEDENCE)
public static class TestConfiguration {
@Bean
@Primary
public FooRepository fooRepository() {
FooRepository mock = mock(FooRepository.class);
// mockbehaviour
return mock;
}
@Bean
@Primary
public FooDao fooDao() {
FooDao mock = mock(FooDao.class);
//Mock behaviour
return mock;
}
@Bean
@Primary
public BarDao barDao() {
BarDao mock = mock(BarDao.class);
//MockBehaviour
return mock;
}
@Bean
@Primary
public BarRepository barRepository() {
BarRepository mock = mock(BarRepository.class);
return mock;
}
}
我现在正在创建几个请求,这些请求被传递给超类进行安全测试,并且(因为所有测试只有一个成功案例)然后我尝试通过verify(mock)验证对Daos和Repositories的相应调用。
Beans通过@Resource
注入Controller,就像我在测试类中使用它一样。
由于某种原因,Daos正在按预期工作(已创建,行为被指定,被调用并且可以被验证),存储库不是 - 创建和使用常规代理。在使用@Order(Ordered.HIGHEST_PRECEDENCE)
之前,简单地跳过了bean创建(并且这样记录),因为已经注册的顶级bean被拒绝被覆盖。
在诉诸于此之后,Repository-beans已被覆盖而不是被跳过(当然,已经被记录)。 bean级别的@Primary
应该确保使用模拟而不是组件扫描创建的实际bean - 以及其他测试实例,它们不启动整个应用程序和嵌入式Mongo,这是有效的按照预期 - 但在这里,它没有。
@Order
@EnableMongoRepositories
- 配置我一直在寻找好几天,总是和我偶然发现的唯一可能的解决方案是:创建一个xml配置(这是一个禁忌,因为我们应该创建一切而不需要xml-文件),使用Fongo(这将需要为这一步导入一个新的依赖,因为数据库测试完全在其他地方发生,然后删除它),或禁用bean覆盖(我完全不知道做并且Spring文档并没有真正帮助 - 是的,方法就在那里,但每当我尝试这样做时,它都不会影响当前的上下文。)
答案 0 :(得分:3)
对不起,这会更适合评论而不是答案,但格式太糟糕了......
不知道为什么它不起作用,但你是否尝试使用@Configuration bean的显式导入而不是使用ComponenScan?
e.g:
@SpringApplicationConfiguration(classes = TestClass.TestConfiguration.class)
public class TestClass extends AbstractTest {
@Configuration
@Import( TestConfig.class )
public static class TestConfiguration {
//...
}
}
@Configuration
@EnableAutoConfiguration(exclude = { EmbeddedMongoAutoConfiguration.class })
// @ComponentScan(value = { "package1", "package2" }) // GET RID OF THIS
@Import( { TestMongoConfiguration.class /*, OtherConfig.class, ... */ } )
public class TestConfig {
}
通过这种方式,您可以控制配置加载方式的顺序。