У меня есть класс с некоторыми бизнес-логиками c и сохраняется в БД после проверки. Сохранение в БД происходит в новом методе с новой транзакцией, и если есть исключение, он будет откатан.
Класс FooProcessor:
public void process(Map<String, List> fooMap, String name) {
final List<FooList> fooList = fooMap.get("fooList");
int successRecordCount = 0;
int errorRecordCount = 0;
for (Foo foo : fooList) {
try {
//Validation logics
saveToDB(foo);
} catch (Exception e) {
this.fooErrorProcessor.insertIntoError(foo);
}
}
}
Класс FooUpdateProcessor:
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
public void saveToDB(Foo foo) {
BarEntity barEntity = foo.getBarEntity;
FooEntity fooEntity = foo.getFooEntity;
BazEntity bazEntity = foo.getBazEntity;
//Business logic
//insert Bar and Baz entities to the table
barDao.save(barEntity);
bazEntity.save(bazEntity);
updateFooEntity(fooEntity);
}
public void updateFooEntity(fooEntity) {
int retryAttempt = 0;
while (true) {
try {
final Optional<QuxEntity> quxOptional = quxDao.findFooByNameAndTypeAndPartId(foo.getName, foo.getType, foo.getPartId);
if (quxOptional.isPresent()) {
QuxEntity quxEntity = quxOptional.get;
quxEntity.setState("Success");
} else {
quxDao.insertintoQux(foo.getName, foo.getType, foo.getPartId, "Success");
}
fooEntity.setStatus("Completed");
fooDao.save(fooEntity);
} catch (Exception e) {
retryAttempt++;
LOGGER.warn("Exception occurred while updating data");
if (retryAttempt >= 2) {
LOGGER.debug("Threshold reached");
throw e;
}
Thread.sleep(500);
}
}
}
Тестовый класс:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ApplicationTest.class)
@TestPropertySource(locations = "classpath:application-test.properties")
@Sql(value = {"classpath:sql/processor/foo_processor_test.sql"}, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED))
public class FooProcessorTest {
private FooProcessor fooProcessor;
private FooUpdateProcessor fooUpdateProcessor;
@Autowired
private FooDao fooDao;
@Autowired
private BarDao barDao;
@Mock
private QuxDao quxDao;
@Autowired
private BazDao bazDao;
@Before
public void setUp() {
fooUpdateProcessor = new FooUpdateProcessor(quxDao, fooDao);
fooProcessor = new FooProcessor(fooUpdateProcessor, fooDao, barDao, quxDao, bazDao);
}
@Test
@Transactional(isolation = Isolation.READ_COMMITTED)
public void validateRollBack() {
List<FooList> fooList = new ArrayList<>();
FooDato fooDto = new FooDto(1212, null, 1L, 2877, 100L, 17502L, 20801L, null, null, 1000L, 2L, LocalDateTime.of(2019, 5, 15, 10, 20, 30));
fooList.add(fooDto);
String fileName = "fooList";
Map<String, List> fooMap = new HashMap<>();
fooMap.put(fileName, fooList);
Mockito.when(this.quxDao.findFooByNameAndTypeAndPartId(any(),any(),any()))
.thenThrow(new RuntimeException("DB Error"))
.thenThrow(new RuntimeException("DB Error"));
this.fooProcessor.process(fooMap, fileName);
TestTransaction.flagForCommit();
TestTransaction.end();
//Verify
long insertedRecordCount = this.barDao.countBarById(1);
long insertedRecordCount = this.fooError.countFooError();
Assert.assertEquals(0L, insertedRecordCount);
Assert.assertEquals(1L, errorRecordCount);
}
}
Откат не работает. Утверждение BarEntity терпит неудачу в junit. Однако при запуске программы откат работает нормально. Как заставить откат работать в тестовом примере junit? Я что-то здесь упускаю?