如果我使用以下设置运行dbunit,并在集成测试中通过HTTP请求数据,则不会获得任何数据,因为数据库是空的。DBUnit将数据写入数据库,但当我通过HTTP请求数据时,它是空的。
这是我的设置: Spring 1.1.7与spring starter(不包括tomcat)、spring starter、spring starter jpa、spring starter test、液基核心、dbunit 2.5.0、spring-test-dbunit 1.1.0。
主要应用课程:
@Configuration
@ComponentScan
@EnableAutoConfiguration
@RestController
@EnableTransactionManagement
@EnableJpaRepositories测试配置(应用程序-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集成测试:
@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));
}我可以把所有的东西都发到这里,比如实体,仓库,控制器,.但是这些组件正在工作,因为我已经通过注入的存储库编写测试到数据库,并通过HTTP获取它。所以问题是通过dbunit导入,它不起作用.我已经成功地在一个较老的投影中使用了dbunit,但没有与spring启动一起使用。也许执行监听器的工作方式与spring引导不一样?
我抛出了dbunit的类并读取了所有的调试日志输出,但是我没有理解它。DBUnit正在使用spring引导创建的dataSource (上面配置的),所以它是同一个数据库。
在启动集成测试时,会发生以下情况:
更新
我正在寻找一种替代dbunit的方法,但找不到任何好的解决方案。那么,如何为集成测试准备数据库呢?实际上,如果数据按预期持久化,我只需要在每次测试或测试之前导入个性化数据。
更新
我使用以下选项连接到h2数据库:
DB_CLOSE_DELAY=-1;MVCC=true;DB_CLOSE_ON_EXIT=FALSE当我删除完整的spring .数据源.* configuration使用标准值创建数据源并启动内存中的h2数据库服务器时。这将在没有我提到的选项的情况下完成,我得到一个org.hibernate.PessimisticLockException,因为dbunit仍然锁定数据库表,并且在测试中发送的HTTP请求没有访问数据库表的权限。这是因为选项MVCC=true;增加了更高的并发性,基本上是什么问题,为什么没有数据:“只有连接‘查看’提交的数据,和自己的更改”。当通过HTTP请求访问数据库时,不存在dbunit的数据,因为dbunit的数据没有提交给spring连接.
那么,有人知道为什么h2 (以及derby)数据库表会被dbunit锁定吗?
发布于 2014-10-10 11:44:57
我终于找到了解决这个问题的办法。
我指出的PessimisticLockException的方向是正确的。DBUnit没有释放数据库连接,这就是为什么spring的连接无法访问锁定的数据库表。
我实现了自己的数据库操作。我使用了customize DBUnit database options选项。
首先,我基于TransactionOperation of DBUnit实现了一个名为DBUnit的类,其不同之处在于,在将auto设置为false之前,删除了check jdbcConnection.getAutoCommit() == false并保存了auto提交值。提交之后,我将值设置为保存的值,使其具有与前面相同的状态:
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);
}
}
}然后我创建了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);
}
}并将其添加到我的测试类中:
@DbUnitConfiguration(databaseOperationLookup = AutoCommitTransactionDatabaseLookup.class)我不确定这是不是更多的黑客。对我的黑客有什么线索吗?
https://stackoverflow.com/questions/26236039
复制相似问题