Как проверить, работает ли транзакционная аннотация Spring boot с помощью Junit

#java #spring #spring-boot #junit #rollback

Вопрос:

Я использую @Transactional для отката при возникновении ошибки. Чтобы убедиться, что эта аннотация работает, я хочу протестировать ее с помощью Junit. Мой код прост. Просто сохраните данные, повторяя 100 данных, используя метод сохранения jpa. Когда метод itemSave дважды повторяет метод saveAll, я хочу создать исключение во время выполнения и убедиться, что таблица элементов откатана и содержимое таблицы соответствует ожиданиям. ————Класс обслуживания—————————

 @Slf4j
@Service
public class SampleService {
    
    @Autowired
    SampleLogic sampleLogic;
    
    @Transactional
    public CommandType execute() {
        try {
            //get items
            List<ItemEntity> itemEntities = sampleLogic.getItems();
            
            //save item data
            sampleLogic.itemSave(itemEntities);
        } catch (Exception e) {
            log.error("Error Happened!!!", e);
             return CommandType.FAILURE;
        }
        return CommandType.SUCCESS;
    }

}

 

——логический класс—————————————-

 @Component
public class SampleLogic {
    
    @Autowired
    SampleRepository sampleRepository;
    
    
    public List<ItemEntity> getItems() {
        
        List<ItemEntity> itemEntities = new ArrayList<>();
        for(int i = 0; i < 1000; i  ) {
            itemEntities.add(new ItemEntity(String.valueOf(i), "itemName"));
        }
        
        return itemEntities;
    }
    
    
    public void itemSave(List<ItemEntity> itemEntities) {
        
        Iterables.partition(itemEntities, 100).forEach(list -> {
            // save data per 100
            sampleRepository.saveAll(itemEntities);
        });
        
    }
    

}
 

——тестовый класс—————————————-

 @ExtendWith(SpringExtension.class)
@TestExecutionListeners({DirtiesContextTestExecutionListener.class,
    DependencyInjectionTestExecutionListener.class, 
    TransactionDbUnitTestExecutionListener.class})
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
public class SampleServiceTest {
    
    @InjectMocks
    private SampleService sampleService;
    
    @Test
    @DatabaseSetup("/itemPrep.xml")
    @ExpectedDatabase(value = "/testdata/CustomerServiceTest/init-data", assertionMode=DatabaseAssertionMode.NON_STRICT)
    void whenSaveMethodCalledRollBackHappen() {
        //
        
        //make sure execute method returns failure and item table is roll backed
        Assertions.assertEquals(CommandType.FAILURE, sampleService.execute());
    }

}
 

I was thinking to insert 100 data first, and when 101st data is inserted, runtime exception is thrown and rollback happens. But I couldn’t make it happen…
I wonder if this could work, or there is any other way to test if roll back happens in this codes.

     @Test
    @DatabaseSetup("/itemPrep.xml")
    @ExpectedDatabase(value = "/testdata/CustomerServiceTest/init-data", assertionMode=DatabaseAssertionMode.NON_STRICT)
    void whenSaveMethodCalledRollBackHappen() {
        //
        List<ItemEntity> itemMockList = Mockito.mock(List.class);
        for(int i = 0; i < 100; i  ) {
            Mockito.when(itemMockList.get(i))
            .thenReturn(new ItemEntity(String.valueOf(i), "itemName"));
        }
        Mockito.when(itemMockList.get(101)).thenThrow(new RuntimeException());
                
        //make sure execute method returns failure and item table is roll backed
        Assertions.assertEquals(CommandType.FAILURE, sampleService.execute());
    }