⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 abstracttransactionaspecttests.java

📁 Java/J2EE application framework based on [Expert One-on-One J2EE Design and Development] by Rod John
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright 2002-2004 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.transaction.interceptor;

import java.lang.reflect.Method;

import junit.framework.TestCase;
import org.easymock.MockControl;

import org.springframework.beans.ITestBean;
import org.springframework.beans.TestBean;
import org.springframework.transaction.CannotCreateTransactionException;
import org.springframework.transaction.NoTransactionException;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.TransactionSystemException;
import org.springframework.transaction.UnexpectedRollbackException;
import org.springframework.transaction.interceptor.TransactionAspectSupport.TransactionInfo;
import org.springframework.transaction.support.DefaultTransactionStatus;

/**
 * Mock object based tests for transaction aspects.
 * True unit test in that it tests how the transaction aspect uses
 * the PlatformTransactionManager helper, rather than indirectly
 * testing the helper implementation.
 * This is a superclass to allow testing both the AOP Alliance MethodInterceptor
 * and AspectJ aspect.
 * @author Rod Johnson
 * @since 16-Mar-2003
*  @version $Id: AbstractTransactionAspectTests.java,v 1.7 2004/08/09 08:30:00 jhoeller Exp $
 */
public abstract class AbstractTransactionAspectTests extends TestCase {
	
	protected Method  exceptionalMethod;
	
	protected Method getNameMethod;
	
	protected Method setNameMethod;
	
	public AbstractTransactionAspectTests() {
		try {
			// Cache the methods we'll be testing
			exceptionalMethod = ITestBean.class.getMethod("exceptional", new Class[] { Throwable.class });
			getNameMethod = ITestBean.class.getMethod("getName", null);
			setNameMethod = ITestBean.class.getMethod("setName", new Class[] { String.class} );
		}
		catch (NoSuchMethodException ex) {
			throw new RuntimeException("Shouldn't happen", ex);
		}
	}
	
	/**
	 * Subclasses must implement this to create an advised object based on the
	 * given target. In the case of AspectJ, the  advised object will already
	 * have been created, as there's no distinction between target and proxy.
	 * In the case of Spring's own AOP framework, a proxy must be created
	 * using a suitably configured transaction interceptor
	 * @param target target if there's a distinct target. If not (AspectJ),
	 * return target.
	 * @return transactional advised object
	 */
	protected abstract Object advised(Object target, PlatformTransactionManager ptm,
	                                  TransactionAttributeSource tas) throws Exception;

	public void testNoTransaction() throws Exception {
		MockControl ptxControl = MockControl.createControl(PlatformTransactionManager.class);
		PlatformTransactionManager ptm = (PlatformTransactionManager) ptxControl.getMock();

		// expect no calls
		ptxControl.replay();

		TestBean tb = new TestBean();
		TransactionAttributeSource tas = new MapTransactionAttributeSource();

		// All the methods in this class use the advised() template method
		// to obtain a transaction object, configured with the given PlatformTransactionManager
		// and transaction attribute source
		ITestBean itb = (ITestBean) advised(tb, ptm, tas);

		checkTransactionStatus(false);
		itb.getName();
		checkTransactionStatus(false);

		ptxControl.verify();
	}

	/**
	 * Check that a transaction is created and committed.
	 */
	public void testTransactionShouldSucceed() throws Exception {
		TransactionAttribute txatt = new DefaultTransactionAttribute();

		Method m = getNameMethod;
		MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
		tas.register(m, txatt);

		TransactionStatus status = transactionStatusForNewTransaction();
		MockControl ptxControl = MockControl.createControl(PlatformTransactionManager.class);
		PlatformTransactionManager ptm = (PlatformTransactionManager) ptxControl.getMock();
		// expect a transaction
		ptm.getTransaction(txatt);
		ptxControl.setReturnValue(status, 1);
		ptm.commit(status);
		ptxControl.setVoidCallable(1);
		ptxControl.replay();

		TestBean tb = new TestBean();
		
		ITestBean itb = (ITestBean) advised(tb, ptm, tas);

		checkTransactionStatus(false);
		// verification!?
		itb.getName();
		checkTransactionStatus(false);

		ptxControl.verify();
	}
	
	/**
	 * Check that a transaction is created and committed.
	 */
	public void testTransactionShouldSucceedWithNotNew() throws Exception {
		TransactionAttribute txatt = new DefaultTransactionAttribute();

		Method m = getNameMethod;
		MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
		tas.register(m, txatt);

		TransactionStatus status = new DefaultTransactionStatus(new Object(), false, false, false, false, null);
		MockControl ptxControl = MockControl.createControl(PlatformTransactionManager.class);
		PlatformTransactionManager ptm = (PlatformTransactionManager) ptxControl.getMock();
		// expect a transaction
		ptm.getTransaction(txatt);
		ptxControl.setReturnValue(status, 1);
		ptm.commit(status);
		ptxControl.setVoidCallable(1);
		ptxControl.replay();

		TestBean tb = new TestBean();

		ITestBean itb = (ITestBean) advised(tb, ptm, tas);

		checkTransactionStatus(false);
		// verification!?
		itb.getName();
		checkTransactionStatus(false);

		ptxControl.verify();
	}

	public void testEnclosingTransactionWithNonTransactionMethodOnAdvisedInside() throws Throwable {
		TransactionAttribute txatt = new DefaultTransactionAttribute();

		Method m = exceptionalMethod;
		MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
		tas.register(m, txatt);

		TransactionStatus status = transactionStatusForNewTransaction();
		MockControl ptxControl = MockControl.createControl(PlatformTransactionManager.class);
		PlatformTransactionManager ptm = (PlatformTransactionManager) ptxControl.getMock();
		// Expect a transaction
		ptm.getTransaction(txatt);
		ptxControl.setReturnValue(status, 1);
		ptm.commit(status);
		ptxControl.setVoidCallable(1);
		ptxControl.replay();
		
		final String spouseName = "innerName";

		TestBean outer = new TestBean() {
			public void exceptional(Throwable t) throws Throwable {
				TransactionInfo ti = TransactionAspectSupport.currentTransactionInfo();
				assertTrue(ti.hasTransaction());
				assertEquals(spouseName, getSpouse().getName());
			}
		};
		TestBean inner = new TestBean() {
			public String getName() {
				// Assert that we're in the inner proxy
				TransactionInfo ti = TransactionAspectSupport.currentTransactionInfo();
				assertFalse(ti.hasTransaction());
				return spouseName;
			}
		};
		
		ITestBean outerProxy = (ITestBean) advised(outer, ptm, tas);
		ITestBean innerProxy = (ITestBean) advised(inner, ptm, tas);
		outer.setSpouse(innerProxy);

		checkTransactionStatus(false);

		// Will invoke inner.getName, which is non-transactional
		outerProxy.exceptional(null);		
		
		checkTransactionStatus(false);

		ptxControl.verify();
	}
	
	public void testEnclosingTransactionWithNestedTransactionOnAdvisedInside() throws Throwable {
		final TransactionAttribute outerTxatt = new DefaultTransactionAttribute();
		final TransactionAttribute innerTxatt = new DefaultTransactionAttribute(TransactionDefinition.PROPAGATION_NESTED);

		Method outerMethod = exceptionalMethod;
		Method innerMethod = getNameMethod;
		MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
		tas.register(outerMethod, outerTxatt);
		tas.register(innerMethod, innerTxatt);

		TransactionStatus outerStatus = transactionStatusForNewTransaction();
		TransactionStatus innerStatus = transactionStatusForNewTransaction();
		
		MockControl ptxControl = MockControl.createControl(PlatformTransactionManager.class);
		PlatformTransactionManager ptm = (PlatformTransactionManager) ptxControl.getMock();
		// Expect a transaction
		ptm.getTransaction(outerTxatt);
		ptxControl.setReturnValue(outerStatus, 1);
		
		ptm.getTransaction(innerTxatt);
		ptxControl.setReturnValue(innerStatus, 1);
		
		ptm.commit(innerStatus);
		ptxControl.setVoidCallable(1);
		
		ptm.commit(outerStatus);
		ptxControl.setVoidCallable(1);
		ptxControl.replay();
		
		final String spouseName = "innerName";

		TestBean outer = new TestBean() {
			public void exceptional(Throwable t) throws Throwable {
				TransactionInfo ti = TransactionAspectSupport.currentTransactionInfo();
				assertTrue(ti.hasTransaction());
				assertEquals(outerTxatt, ti.getTransactionAttribute());
				assertEquals(spouseName, getSpouse().getName());
			}
		};
		TestBean inner = new TestBean() {
			public String getName() {
				// Assert that we're in the inner proxy
				TransactionInfo ti = TransactionAspectSupport.currentTransactionInfo();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -