Dav*_*vid 5 java spring dbunit spring-data spring-boot
如果我使用以下设置运行dbunit并在集成测试中通过HTTP请求数据,我没有得到任何数据,因为数据库是空的.DBUnit将数据写入数据库,但是当我通过HTTP请求数据时它是空的.
这是我的设置:Spring Boot 1.1.7 with spring-boot-starter-web(不包括tomcat),spring-boot-starter-jetty,spring-boot-starter-data-jpa,spring-boot-starter-test,liquibase -core,dbunit 2.5.0,spring-test-dbunit 1.1.0
主要应用类别:
@Configuration
@ComponentScan
@EnableAutoConfiguration
@RestController
@EnableTransactionManagement
@EnableJpaRepositories
Run Code Online (Sandbox Code Playgroud)
测试配置(application-test.yaml):
logging.level.org.springframework: DEBUG
logging.level.org.dbunit: DEBUG
spring.jpa.properties.hibernate.hbm2ddl.auto: update
spring.jpa.database: h2
spring.jpa.show-sql: true
// setting these properties to access the database via h2 console
spring.datasource.url: jdbc:h2:tcp://localhost/mem:my_db;DB_CLOSE_DELAY=-1;MVCC=true;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.username: sa
spring.datasource.password: sa
spring.datasource.driverClassName: org.h2.Driver
spring.jpa.database-platform: org.hibernate.dialect.H2Dialect
liquibase.change-log: classpath:/db/changelog/db-master.xml
Run Code Online (Sandbox Code Playgroud)
整合测试:
@ActiveProfiles("test")
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = HDImageService.class)
@TestExecutionListeners({
DependencyInjectionTestExecutionListener.class,
DbUnitTestExecutionListener.class })
@WebAppConfiguration
@IntegrationTest("server.port:0")
@DatabaseSetup("/database_seed.xml")
@DatabaseTearDown(value = "/database_tear_down.xml", type = DatabaseOperation.DELETE_ALL)
// test
@Test
public void get_works() throws Exception {
// given
String url = host + port + "/my-resource/1";
// when
ResponseEntity<String> response = template.getForEntity(url, String.class);
// then
assertThat(response.getStatusCode(), is(HttpStatus.OK));
}
Run Code Online (Sandbox Code Playgroud)
我可以在这里发布其他所有内容,例如实体,存储库,控制器......但是这些组件正在工作,因为我已经通过注入的存储库写入测试数据库并通过HTTP获取它.所以问题是通过dbunit导入,这是行不通的...我已经在较旧的预测中成功使用了dbunit,但没有与spring boot一起使用.也许执行监听器的工作方式与spring boot不相似?
我调试了丢弃dbunit的类并读取所有调试日志输出,但我没有得到它.DBUnit正在使用spring boot创建的dataSource(上面配置的),所以它是同一个数据库.
在开始集成测试时,会发生以下情况:
- liquibase基于liquibase配置创建数据库模式(也许jpa之前已经推送过模式?)
- DBUnit插入数据库(表示日志输出和调试)
- 获取404不发现(当在具有给定ID的数据库中找不到条目时,我返回404)
更新:
我正在寻找dbunit的替代品,但找不到任何好的解决方案.那么如何为集成测试准备数据库呢?实际上,如果数据按预期持久化,我只需要在每次测试或测试之前导入单个数据.
更新:
我使用以下选项连接到h2数据库:
DB_CLOSE_DELAY=-1;MVCC=true;DB_CLOSE_ON_EXIT=FALSE
Run Code Online (Sandbox Code Playgroud)
当我删除完整的spring.datasource.*配置弹簧正在创建具有标准值的数据源并启动内存中的h2数据库服务器.这将在没有我提到的选项的情况下完成,org.hibernate.PessimisticLockException因为dbunit仍然锁定数据库表,并且在测试中发送的HTTP请求无法访问数据库表.这是因为选项MVCC=true;增加了更高的并发性,基本上是问题所在,为什么没有数据存在:"仅连接"参见"已提交的数据和自己的更改".通过HTTP请求访问数据库时,dbunit的数据不存在,因为没有为spring连接提交dbunit的数据...
那么,有谁知道为什么h2(以及derby)数据库表被dbunit锁定?
我终于找到了解决这个问题的方法.
这是PessimisticLockException我指向的地方的正确方向.DBUnit没有释放数据库连接,这就是为什么spring连接无法访问锁定的数据库表的原因.
我实现了自己的数据库操作.我使用该选项来自定义DBUnit数据库选项.
首先,我实现了一个AutoCommitTransactionOperation基于TransactionOperationDBUnit 调用的类,不同之处在于我将jdbcConnection.getAutoCommit() == false自动提交设置为false之前删除了检查并保存了自动提交值.在提交之后我将值设置回保存的值,以具有与之前相同的状态:
public class AutoCommitTransactionOperation extends DatabaseOperation {
private final DatabaseOperation _operation;
public AutoCommitTransactionOperation(DatabaseOperation operation) {
_operation = operation;
}
public static final DatabaseOperation AUTO_COMMIT_TRANSACTION(DatabaseOperation operation) {
return new AutoCommitTransactionOperation(operation);
}
public void execute(IDatabaseConnection connection, IDataSet dataSet) throws DatabaseUnitException, SQLException {
logger.debug("execute(connection={}, dataSet={}) - start", connection, dataSet);
IDatabaseConnection databaseConnection = connection;
Connection jdbcConnection = databaseConnection.getConnection();
boolean autoCommit = jdbcConnection.getAutoCommit();
jdbcConnection.setAutoCommit(false);
try {
_operation.execute(databaseConnection, dataSet);
jdbcConnection.commit();
} catch (DatabaseUnitException e) {
jdbcConnection.rollback();
throw e;
} catch (SQLException e) {
jdbcConnection.rollback();
throw e;
} catch (RuntimeException e) {
jdbcConnection.rollback();
throw e;
} finally {
jdbcConnection.setAutoCommit(autoCommit);
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后我创建了DatabaseLookup.
public class AutoCommitTransactionDatabaseLookup extends DefaultDatabaseOperationLookup {
@Override
public org.dbunit.operation.DatabaseOperation get(DatabaseOperation operation) {
if (operation == operation.CLEAN_INSERT) {
return AutoCommitTransactionOperation.AUTO_COMMIT_TRANSACTION(org.dbunit.operation.DatabaseOperation.CLEAN_INSERT);
}
return super.get(operation);
}
}
Run Code Online (Sandbox Code Playgroud)
并将其添加到我的测试类:
@DbUnitConfiguration(databaseOperationLookup = AutoCommitTransactionDatabaseLookup.class)
Run Code Online (Sandbox Code Playgroud)
我不确定这是否更加黑客......对我的黑客有什么暗示?
| 归档时间: |
|
| 查看次数: |
5666 次 |
| 最近记录: |