Reputation: 37946
Test class declaration
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { TestH2Config.class })
@TestExecutionListeners({
DependencyInjectionTestExecutionListener.class,
DbUnitTestExecutionListener.class,
TransactionalTestExecutionListener.class
})
@TransactionConfiguration(defaultRollback = true)
@Transactional
public class BookServiceIT {
// ... dependencies injection goes here (omitted for brevity)
@Test
@DatabaseSetup("/datasets/import.xml")
public void testCase1() throws Exception {
// .. create Book in Organization(id=2)
// ... read and create data in database (omitted for brevity)
}
}
test/resources/datasets/import.xml
<?xml version='1.0' encoding='UTF-8'?>
<dataset>
<Organization id="2" name="Gov. Library" inactive="false" />
</dataset>
Maven command that is used to run tests:
mvn verify -T 1C
I'm attaching an exception stack trace (test fails only in Codeship Linux environment):
WARNING: Caught exception while allowing TestExecutionListener [com.github.springtestdbunit.TransactionDbUnitTestExecutionListener@3f191a96] to process 'before' execution of test method [public void com.test.integration.BookServiceIT.testCase1() throws java.lang.Exception] for test instance [com.test.integration.BookServiceIT@15f18e5] org.h2.jdbc.JdbcSQLException: Referential integrity constraint violation: "FK_JNCMPQJWFCJEXX62EA1P06VLP: ITEST.BOOK FOREIGN KEY(LIBRARY_ID) REFERENCES ITEST.ORGANIZATION(ID) (2)"; SQL statement:delete from ORGANIZATION [23503-195]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:345)
at org.h2.message.DbException.get(DbException.java:179)
at org.h2.message.DbException.get(DbException.java:155)
at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:425)
at org.h2.constraint.ConstraintReferential.checkRowRefTable(ConstraintReferential.java:442)
at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:317)
at org.h2.table.Table.fireConstraints(Table.java:976)
at org.h2.table.Table.fireAfterRow(Table.java:994)
at org.h2.command.dml.Delete.update(Delete.java:101)
at org.h2.command.CommandContainer.update(CommandContainer.java:101)
at org.h2.command.Command.executeUpdate(Command.java:260)
at org.h2.jdbc.JdbcStatement.executeInternal(JdbcStatement.java:193)
at org.h2.jdbc.JdbcStatement.execute(JdbcStatement.java:165)
at org.apache.commons.dbcp.DelegatingStatement.execute(DelegatingStatement.java:264)
at org.apache.commons.dbcp.DelegatingStatement.execute(DelegatingStatement.java:264)
at org.dbunit.database.statement.SimpleStatement.executeBatch(SimpleStatement.java:69)
at org.dbunit.operation.DeleteAllOperation.execute(DeleteAllOperation.java:126)
at org.dbunit.operation.CompositeOperation.execute(CompositeOperation.java:79)
at com.github.springtestdbunit.DbUnitRunner.setupOrTeardown(DbUnitRunner.java:162)
at com.github.springtestdbunit.DbUnitRunner.beforeTestMethod(DbUnitRunner.java:60)
at com.github.springtestdbunit.DbUnitTestExecutionListener.beforeTestMethod(DbUnitTestExecutionListener.java:160)
at com.github.springtestdbunit.TestExecutionListenerChain$3.call(TestExecutionListenerChain.java:93)
at com.github.springtestdbunit.TestExecutionListenerChain.runChain(TestExecutionListenerChain.java:126)
at com.github.springtestdbunit.TestExecutionListenerChain.forwards(TestExecutionListenerChain.java:115)
at com.github.springtestdbunit.TestExecutionListenerChain.beforeTestMethod(TestExecutionListenerChain.java:91)
at org.springframework.test.context.TestContextManager.beforeTestMethod(TestContextManager.java:249)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:70)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:224)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:83)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:163)
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128)
at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103)
I've tried to use other execution listeners (that I've found in DbUnit documentation), but I've got the same exception...
@TestExecutionListeners({
DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class,
TransactionDbUnitTestExecutionListener.class
})
UPD.: I've tried to add an explicit teardown: deleted the Book in the end of testCase() method. But the exception still persists.
Upvotes: 0
Views: 2272
Reputation: 953
dbUnit deletes the rows in the reverse order of the data listed in the dataset files. Ensure the files have the rows with foreign keys placed after the ones with the primary keys/one side of the relationship.
Update: A book table row exists from the test, so tell dbUnit to delete it too. One way is to add an empty table for the foreign key table to the dataset file after the primary table:
<book/>
So the dbUnit teardown operation sees that table and cleans it up too.
Upvotes: 3
Reputation: 37946
I've changed the behaviour of DbUnit by specifying type = DatabaseOperation.REFRESH
. Now it doesn't clean the database after test and there's no JDBC exception.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { TestH2Config.class })
@TestExecutionListeners({
DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class,
TransactionDbUnitTestExecutionListener.class
})
@Transactional
public class BookServiceIT {
// ... dependencies injection goes here (omitted for brevity)
@Test
@DatabaseSetup(value = "/datasets/import.xml", type = DatabaseOperation.REFRESH)
public void testCase1() throws Exception {
// .. create Book in Organization(id=2)
// ... read and create data in database (omitted for brevity)
// .. delete the Book
}
}
See @DatabaseSetup documentation.
Upvotes: 0
Reputation: 2711
It says right there in your stack trace:
org.h2.jdbc.JdbcSQLException: Referential integrity constraint violation: "FK_JNCMPQJWFCJEXX62EA1P06VLP: ITEST.BOOK FOREIGN KEY(LIBRARY_ID) REFERENCES ITEST.ORGANIZATION(ID) (2)"; SQL statement:delete from ORGANIZATION [23503-195]
So you're deleting from table ORGANIZATION
when there are still records in the BOOK
table that refer to the ORGANIZATION
table via the FK_JNCMPQJWFCJEXX62EA1P06VLP
foreign key.
Do you have special code to tear down the database? If not, you may need to write it explicitly, or define your foreign key to be ON DELETE CASCADE
if your business requirements allow that.
Upvotes: 0