001package io.ebean.test; 002 003import io.ebean.DB; 004import io.ebean.Transaction; 005import io.ebeaninternal.api.HelpScopeTrans; 006 007/** 008 * Helper methods for testing. 009 */ 010public class ForTests { 011 012 /** 013 * Enable or disable <code>@Transactional</code> methods. 014 * <p> 015 * This is intended for testing purposes such that tests 016 * on code with {@code @Transactional} methods don't actually 017 * start or complete transactions. 018 * </p> 019 * 020 * @param enable Set false to disable {@code @Transactional} methods 021 */ 022 public static void enableTransactional(boolean enable) { 023 HelpScopeTrans.setEnabled(enable); 024 } 025 026 /** 027 * Run the closure with <code>@Transactional</code> methods 028 * effectively disabled (they won't create/commit transactions). 029 */ 030 public static void noTransactional(Runnable run) { 031 try { 032 enableTransactional(false); 033 run.run(); 034 } finally { 035 enableTransactional(true); 036 } 037 } 038 039 /** 040 * All transactions started in the closure are effectively rolled back. 041 * <p> 042 * This creates a wrapping transaction that uses {@link Transaction#setNestedUseSavepoint()}. 043 * All nested transactions are created as savepoints. On completion the wrapping 044 * transaction is rolled back. 045 * </p> 046 * 047 * @param run Closure that runs such that all the transactions are rolled back. 048 */ 049 public static void rollbackAll(Runnable run) { 050 051 try (Transaction transaction = DB.beginTransaction()) { 052 transaction.setNestedUseSavepoint(); 053 run.run(); 054 055 transaction.rollback(); 056 } 057 } 058 059 /** 060 * Create and return a RollbackAll which should be closed at the end of the test(s). 061 * <p> 062 * In tests for <code>@Before</code> we create the rollbackAll and on 063 * <code>@After</code> we <code>close()</code> it effectively rolling 064 * back all changes made during test execution. 065 * </p> 066 * 067 * <pre>{@code 068 * 069 * private ForTests.RollbackAll rollbackAll; 070 * 071 * @Before 072 * public void before() { 073 * rollbackAll = ForTests.createRollbackAll(); 074 * } 075 * 076 * @After 077 * public void after() { 078 * rollbackAll.close(); 079 * } 080 * 081 * ... tests execute and everything is rolled back 082 * 083 * 084 * }</pre> 085 */ 086 public static RollbackAll createRollbackAll() { 087 088 final Transaction transaction = DB.beginTransaction(); 089 transaction.setNestedUseSavepoint(); 090 return new RollbackAll(transaction); 091 } 092 093 /** 094 * A wrapping transaction used in test code to rollback all changes. 095 * <p> 096 * We must ensure that <code>close()</code> is called. 097 * </p> 098 */ 099 public static class RollbackAll implements AutoCloseable { 100 101 private final Transaction transaction; 102 103 private RollbackAll(Transaction transaction) { 104 this.transaction = transaction; 105 } 106 107 /** 108 * Rollback the wrapping transaction. 109 */ 110 @Override 111 public void close() { 112 transaction.rollback(); 113 } 114 } 115}