2

Ich schreibe Komponententests für meinen Service. Das Problem besteht darin, dass Transaktionen nach Abschluss des Tests nicht automatisch durch den Spring-Boot-Vorgang zurückgesetzt werden.Spring Boot, Transaktion ist kein Rollback nach Test

Hier ist meine Tests:

@SpringApplicationConfiguration(classes = { TestApplicationConfiguration.class, TestDataSourceConfiguration.class }) 
@RunWith(SpringJUnit4ClassRunner.class) 
public class BoardServiceTest { 

@Autowired 
    private UserService userService; 

    @Autowired 
    private CardService cardService; 

    @Autowired 
    private BoardCardService boardCardService; 

    @Autowired 
    private BoardService boardService; 

    @Autowired 
    private CommonBoardService commonBoardService; 

    @Autowired 
    private AuthorityService authorityService; 

    @Test(expected = CommonException.class) 
    @Transactional 
    public void testCreateBoardStatusAFK() { 
     final User admin = userService.findUserById(1l); 
     admin.setCurrentBoard(null); 

     Board board = boardService.startBoard(admin); 
     assertEquals(board, admin.getCurrentBoard()); 

     // Board has status IN_PROGRESS, current time < timeToComplete 
     board.setSelectedCardsCount(boardService.getDefaultCardsToSelectCount() - 1); 
     board.setTimeToComplete(DateUtils.addHours(new Date(), boardService.getDefaultMinsToComplete())); 
     board = commonBoardService.save(board); 
     board = boardService.startBoard(admin); 
     assertEquals(admin.getCurrentBoard().getStatus(), Board.IN_PROGRESS); 

     // Board has status IN_PROGRESS, current time > timeToComplete 
     board.setTimeToComplete(DateUtils.addHours(new Date(), -1)); 
     board = commonBoardService.save(board); 
     board = boardService.startBoard(admin); 

     assertEquals(admin.getCurrentBoard().getStatus(), Board.AFK); 
    } 
} 

Nach der Testdurchführung, die entsprechende Tabelle in Test db durch neuen Rekord aufgefüllt.

Bitte, sagen Sie mir, wie dieses Problem zu lösen?

Update:

Hier ist die Umsetzung meiner Service-Methode, dass während des Tests aufgerufen wird:

@Override 
    @Transactional(propagation = Propagation.REQUIRES_NEW) 
    public Board update(Board board, Date finishedDate, Integer status) { 
     board.setStatus(status); 
     board.setFinishedDate(finishedDate); 

     return boardRepository.save(board); 
    } 

Wie können Sie sehen, neue Transaktion geöffnet wird, wenn diese Methode aufgerufen wird. In meiner Debug-Konsole sehe ich die folgenden Informationen, nach der Aktualisierung abgeschlossen ist:

Hibernate: select nextval ('boards_id_seq') 
Hibernate: insert into boards (created_date, updated_date, cards_to_hold, cards_to_select, finished_date, holded_cards_count, selected_cards_count, started_date, status, time_to_complete, time_to_next_board, user_id, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 

Ich verstehe nicht, warum Hibernate neue Einheit in db erstellen, obwohl ich einen bestehenden bin zu aktualisieren. Also, vielleicht ist das der Grund für ein solches Verhalten?

+0

Wenn Sie einen Komponententest schreiben, würde es nicht einfacher machen, wenn Sie die Klassen verspotten, die Dinge in der Datenbank speichern? (Wie ein Repository, Entitymanager, ...) – g00glen00b

+0

@ g00glen00b, Nun, wie der Frühling die Transaktionen in Tests verwaltet, deshalb möchte ich andere Komponenten nicht verspotten. –

+0

Grüße zum Zurückrollen im Test. Sie können Ihre Testklasse mit ** @ TransactionConfiguration (defaultRollback = true) ** kommentieren. Dies führt dazu, dass die Transaktion immer zurückgesetzt wird. Beschriften Sie auch die Testklasse mit ** @ Transactional **, um sicherzustellen, dass alle Tests zurückgesetzt werden –

Antwort

0

Sie müssen in Ihrer Transaktionsannotation einen RollbackFor Parameter angeben. @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class) Standard-Rollback funktioniert nur für ungeprüfte Ausnahmen (Instanz von RuntimeException oder Error) mit Transaktionsannotation