-
Notifications
You must be signed in to change notification settings - Fork 38.5k
Support rollbackFor attribute of @Transactional in the TestContext framework #23138
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
That's an interesting use case. This has been the behavior of test-managed transactions since over a decade, though no one has ever raised this issue before. In summary, you are asking for the TestContext framework to honor the Is that correct? Note to self: the |
Yes, it's correct. The problem appears very accidentally. May I submit a pull request to make the SpringTest framework to honor the |
Thanks for the confirmation.
Please hold off on submitting a PR until the team decides if we want to support this feature. Tentatively slated for 5.2 RC1 for consideration. |
Got it, thanks, |
Team Decision: We have decided not to support the Rationale: Spring's testing support has never honored the Workaround: use the In any case, the documentation can be improved with regard to which attributes in |
To achieve the desired behavior, you need to introduce a try-catch block within your test method. Within the catch-block you need to invoke The following JUnit Jupiter based test class demonstrates how to do this.
When executing this test class, we see the following output to SYS_OUT.
The code is split into chunks to avoid the need to scroll. @SpringJUnitConfig
@Transactional
@Commit
class CommittedTransactionalTests {
@Autowired
JdbcTemplate jdbcTemplate; @Test
void customRollbackWithTestTransactionApi() throws Throwable {
try {
serviceMethod();
}
catch (Throwable t) {
TestTransaction.flagForRollback();
throw t;
}
}
@Test
void customRollbackForApi() throws Throwable {
// rollbackFor(FileNotFoundException.class, () -> serviceMethod());
rollbackFor(Exception.class, () -> serviceMethod());
} @BeforeTransaction
void beforeTransaction() {
assertZeroUsers("before");
}
@AfterTransaction
void afterTransaction() {
assertZeroUsers("after");
}
void assertZeroUsers(String phase) {
int numUsers = JdbcTestUtils.countRowsInTable(this.jdbcTemplate, "user");
System.out.printf("Number of users in DB %s transaction: %d%n", phase, numUsers);
assertThat(numUsers).isEqualTo(0);
} static void rollbackFor(Class<? extends Throwable> exceptionType, Executable executable) throws Throwable {
try {
executable.execute();
}
catch (Throwable t) {
if (exceptionType.isInstance(t)) {
TestTransaction.flagForRollback();
}
throw t;
}
}
@FunctionalInterface
interface Executable {
void execute() throws Throwable;
}
private void serviceMethod() throws Exception {
this.jdbcTemplate.update("INSERT INTO user VALUES('Dilbert')");
throw new Exception("Business Exception");
} @Configuration
static class Config {
@Bean
JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
@Bean
PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean
DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.generateUniqueName(true)
.addScript("classpath:/test-schema.sql")
.build();
}
}
} |
Superseded by gh-23149 |
It works for me though the way to support rollback is not such straightforward. Thanks for detailed instructions. |
Uh oh!
There was an error while loading. Please reload this page.
Description
Transactional test methods wouldn't rollback for exception,when annotated by
@Commit
or@Rollback(false)
.For example, the following
roleService.saveOrUpdate(sysRole)
would commit.This would cause partial DML operation commit.
Suggestion
The following code snippet force commit or rollback according to
flaggedForRollback
I would like to make some changes, determine if there is a matching exception in the testContext.
The text was updated successfully, but these errors were encountered: