Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,19 @@

import io.ebean.DB;
import io.ebean.Transaction;
import io.ebean.test.PersistenceContextAccess;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.transaction.annotation.Transactional;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.in;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

Expand Down Expand Up @@ -42,6 +46,24 @@ public EbeanSpringModuleTest() {
super();
}

@Transactional
@Rollback
@Test
public void testWithRollback() {
// setup
User user = new User();
user.setName("rollback1");
DB.save(user);

// this loads the user into the [transaction scoped] persistence context
User found = DB.find(User.class, user.getOid());
found.setName("mutated");

PersistenceContextAccess.clear();

userService.insideTestRollback(user.getOid());
}

/**
* Test app.
*/
Expand Down
2 changes: 2 additions & 0 deletions ebean-spring-txn/src/test/java/org/example/UserService.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ public interface UserService {
void batchInsert();

void requiresNew();

void insideTestRollback(long oid);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import java.util.ArrayList;
import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

/**
* The Class UserServiceImpl.
*
Expand All @@ -28,6 +30,13 @@ public class UserServiceImpl implements UserService, ApplicationContextAware {
@Autowired
private Database ebeanServer;

@Override
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
public void insideTestRollback(long oid) {
User found = ebeanServer.find(User.class, oid);
assertThat(found.getName()).isEqualTo("rollback1");
}

@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
public void save(User user) {
ebeanServer.save(user);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package io.ebean.test;

import io.ebean.Transaction;
import io.ebean.bean.PersistenceContext;
import io.ebeaninternal.api.SpiTransaction;

/**
* Provides tests access to the persistence context.
* <p>
* Expected to be used with tests that use Spring test {@code @Rollback} {@code @Transactional}.
* These tests have an outer transaction that will rollback. The issue is that test setup code
* is now running in the SAME TRANSACTION as the code under test (main code we are testing) and
* that the Ebean Persistence Context is transaction scoped - so the test setup code can load
* entities into the ebean persistence context during the test setup phase - we SHOULD clear the
* persistence context AFTER the setup phase of the test and BEFORE we run the code under test.
*
* <pre>{@code
*
* @Test
* @Transactional // spring transactional
* @Rollback // spring test rollback
* void myTestWithSpringRollback() {
*
* // Test Setup: this MIGHT load entities into the persistence context
* performTestSetup();
*
* // clear out the persistence context
* PersistenceContextAccess.clear();
*
* // Act
* performActionsWeAreTestingHere();
*
* // Assert
* assertThat(...)
*
* }
*
* }</pre>
*/
public class PersistenceContextAccess {

/**
* Clear the persistence context of the current transaction.
* <p>
* This is expected to be called after test setup phase and before
* the test executes the code we are looking to test - so
* AFTER "setup" and BEFORE "act".
*/
public static void clear() {
Transaction current = Transaction.current();
if (current != null) {
SpiTransaction spiTransaction = (SpiTransaction) current;
PersistenceContext pc = spiTransaction.persistenceContext();
if (pc != null) {
pc.clear();
}
}
}
}