/* * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.test.context.transaction; import org.springframework.test.context.TestExecutionListeners; import org.springframework.transaction.TransactionStatus; import org.springframework.util.Assert; /** * {@code TestTransaction} provides a collection of static utility methods for * programmatic interaction with <em>test-managed transactions</em> within * <em>test</em> methods, <em>before</em> methods, and <em>after</em> methods. * * <p>Consult the javadocs for {@link TransactionalTestExecutionListener} * for a detailed explanation of <em>test-managed transactions</em>. * * <p>Support for {@code TestTransaction} is automatically available whenever * the {@code TransactionalTestExecutionListener} is enabled. Note that the * {@code TransactionalTestExecutionListener} is typically enabled by default, * but it can also be manually enabled via the * {@link TestExecutionListeners @TestExecutionListeners} annotation. * * @author Sam Brannen * @since 4.1 * @see TransactionalTestExecutionListener */ public class TestTransaction { /** * Determine whether a test-managed transaction is currently <em>active</em>. * @return {@code true} if a test-managed transaction is currently active * @see #start() * @see #end() */ public static boolean isActive() { TransactionContext transactionContext = TransactionContextHolder.getCurrentTransactionContext(); if (transactionContext != null) { TransactionStatus transactionStatus = transactionContext.getTransactionStatus(); return (transactionStatus != null) && (!transactionStatus.isCompleted()); } // else return false; } /** * Determine whether the current test-managed transaction has been * {@linkplain #flagForRollback() flagged for rollback} or * {@linkplain #flagForCommit() flagged for commit}. * @return {@code true} if the current test-managed transaction is flagged * to be rolled back; {@code false} if the current test-managed transaction * is flagged to be committed * @throws IllegalStateException if a transaction is not active for the * current test * @see #isActive() * @see #flagForRollback() * @see #flagForCommit() */ public static boolean isFlaggedForRollback() { return requireCurrentTransactionContext().isFlaggedForRollback(); } /** * Flag the current test-managed transaction for <em>rollback</em>. * <p>Invoking this method will <em>not</em> end the current transaction. * Rather, the value of this flag will be used to determine whether or not * the current test-managed transaction should be rolled back or committed * once it is {@linkplain #end ended}. * @throws IllegalStateException if a transaction is not active for the * current test * @see #isActive() * @see #isFlaggedForRollback() * @see #start() * @see #end() */ public static void flagForRollback() { setFlaggedForRollback(true); } /** * Flag the current test-managed transaction for <em>commit</em>. * <p>Invoking this method will <em>not</em> end the current transaction. * Rather, the value of this flag will be used to determine whether or not * the current test-managed transaction should be rolled back or committed * once it is {@linkplain #end ended}. * @throws IllegalStateException if a transaction is not active for the * current test * @see #isActive() * @see #isFlaggedForRollback() * @see #start() * @see #end() */ public static void flagForCommit() { setFlaggedForRollback(false); } /** * Start a new test-managed transaction. * <p>Only call this method if {@link #end} has been called or if no * transaction has been previously started. * @throws IllegalStateException if the transaction context could not be * retrieved or if a transaction is already active for the current test * @see #isActive() * @see #end() */ public static void start() { requireCurrentTransactionContext().startTransaction(); } /** * Immediately force a <em>commit</em> or <em>rollback</em> of the current * test-managed transaction, according to the {@linkplain #isFlaggedForRollback * rollback flag}. * @throws IllegalStateException if the transaction context could not be * retrieved or if a transaction is not active for the current test * @see #isActive() * @see #start() */ public static void end() { requireCurrentTransactionContext().endTransaction(); } private static TransactionContext requireCurrentTransactionContext() { TransactionContext txContext = TransactionContextHolder.getCurrentTransactionContext(); Assert.state(txContext != null, "TransactionContext is not active"); return txContext; } private static void setFlaggedForRollback(boolean flag) { requireCurrentTransactionContext().setFlaggedForRollback(flag); } }