spring之如何在集成测试期间配置 Spring Boot 以包装 DataSource
我的目标是进行集成测试,以确保在查找期间不会发生太多数据库查询。 (这有助于我们捕获由于不正确的 JPA 配置而导致的 n+1 个查询)
我知道数据库连接是正确的,因为无论何时 MyDataSourceWrapperConfiguration 在测试运行期间都没有配置问题不包括在测试中。但是,一旦添加,就会发生循环依赖。 (见下面的错误)我相信 @Primary为了让 JPA/JDBC 代码使用正确的 DataSource 是必需的实例。MyDataSourceWrapper是一个自定义类,它跟踪给定事务发生的查询数量,但它将真实的数据库工作委托(delegate)给 DataSource通过构造函数传入。
错误:
The dependencies of some of the beans in the application context form a cycle:
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
┌─────┐
| databaseQueryCounterProxyDataSource defined in me.testsupport.database.MyDataSourceWrapperConfiguration
↑ ↓
| dataSource defined in org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Tomcat
↑ ↓
| dataSourceInitializer
└─────┘
我的配置:
@Configuration
public class MyDataSourceWrapperConfiguration {
@Primary
@Bean
DataSource databaseQueryCounterProxyDataSource(final DataSource delegate) {
return MyDataSourceWrapper(delegate);
}
}
我的测试:
@ActiveProfiles({ "it" })
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration({ DatabaseConnectionConfiguration.class, DatabaseQueryCounterConfiguration.class })
@EnableAutoConfiguration
public class EngApplicationRepositoryIT {
@Rule
public MyDatabaseQueryCounter databaseQueryCounter = new MyDatabaseQueryCounter ();
@Rule
public ErrorCollector errorCollector = new ErrorCollector();
@Autowired
MyRepository repository;
@Test
public void test() {
this.repository.loadData();
this.errorCollector.checkThat(this.databaseQueryCounter.getSelectCounts(), is(lessThan(10)));
}
}
更新:这个原始问题是针对 springboot 1.5 的。然而,接受的答案反射(reflect)了@rajadilipkolli 的答案适用于springboot 2.x
请您参考如下方法:
在您的情况下,您将获得 2 DataSource可能不是您想要的实例。而是使用 BeanPostProcessor这是实际为此设计的组件。另见Spring Reference Guide .
创建并注册 BeanPostProcessor包装。
public class DataSourceWrapper implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) {
if (bean instanceof DataSource) {
return new MyDataSourceWrapper((DataSource)bean);
}
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
然后只需将其注册为
@Bean而不是你的
MyDataSourceWrapper .
提示:而不是滚动你自己的包装
DataSource您可能对
datasource-proxy 感兴趣结合
datasource-assert它已经具有计数器等支持(节省您维护自己的组件)。
1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。



