Skip to content

Commit

Permalink
Polish AOP tests
Browse files Browse the repository at this point in the history
  • Loading branch information
sbrannen committed Dec 1, 2024
1 parent 51956fa commit 172c8b2
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 84 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class AspectJAutoProxyCreatorTests {
void aspectsAreApplied() {
ClassPathXmlApplicationContext bf = newContext("aspects.xml");

ITestBean tb = (ITestBean) bf.getBean("adrian");
ITestBean tb = bf.getBean("adrian", ITestBean.class);
assertThat(tb.getAge()).isEqualTo(68);
MethodInvokingFactoryBean factoryBean = (MethodInvokingFactoryBean) bf.getBean("&factoryBean");
assertThat(AopUtils.isAopProxy(factoryBean.getTargetObject())).isTrue();
Expand All @@ -96,7 +96,7 @@ void aspectsAreApplied() {
void multipleAspectsWithParameterApplied() {
ClassPathXmlApplicationContext bf = newContext("aspects.xml");

ITestBean tb = (ITestBean) bf.getBean("adrian");
ITestBean tb = bf.getBean("adrian", ITestBean.class);
tb.setAge(10);
assertThat(tb.getAge()).isEqualTo(20);
}
Expand All @@ -105,16 +105,16 @@ void multipleAspectsWithParameterApplied() {
void aspectsAreAppliedInDefinedOrder() {
ClassPathXmlApplicationContext bf = newContext("aspectsWithOrdering.xml");

ITestBean tb = (ITestBean) bf.getBean("adrian");
ITestBean tb = bf.getBean("adrian", ITestBean.class);
assertThat(tb.getAge()).isEqualTo(71);
}

@Test
void aspectsAndAdvisorAreApplied() {
ClassPathXmlApplicationContext ac = newContext("aspectsPlusAdvisor.xml");

ITestBean shouldBeWeaved = (ITestBean) ac.getBean("adrian");
doTestAspectsAndAdvisorAreApplied(ac, shouldBeWeaved);
ITestBean shouldBeWoven = ac.getBean("adrian", ITestBean.class);
assertAspectsAndAdvisorAreApplied(ac, shouldBeWoven);
}

@Test
Expand All @@ -124,20 +124,22 @@ void aspectsAndAdvisorAreAppliedEvenIfComingFromParentFactory() {
GenericApplicationContext childAc = new GenericApplicationContext(ac);
// Create a child factory with a bean that should be woven
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
bd.getPropertyValues().addPropertyValue(new PropertyValue("name", "Adrian"))
bd.getPropertyValues()
.addPropertyValue(new PropertyValue("name", "Adrian"))
.addPropertyValue(new PropertyValue("age", 34));
childAc.registerBeanDefinition("adrian2", bd);
// Register the advisor auto proxy creator with subclass
childAc.registerBeanDefinition(AnnotationAwareAspectJAutoProxyCreator.class.getName(), new RootBeanDefinition(
AnnotationAwareAspectJAutoProxyCreator.class));
childAc.registerBeanDefinition(AnnotationAwareAspectJAutoProxyCreator.class.getName(),
new RootBeanDefinition(AnnotationAwareAspectJAutoProxyCreator.class));
childAc.refresh();

ITestBean beanFromChildContextThatShouldBeWeaved = (ITestBean) childAc.getBean("adrian2");
//testAspectsAndAdvisorAreApplied(childAc, (ITestBean) ac.getBean("adrian"));
doTestAspectsAndAdvisorAreApplied(childAc, beanFromChildContextThatShouldBeWeaved);
ITestBean beanFromParentContextThatShouldBeWoven = ac.getBean("adrian", ITestBean.class);
ITestBean beanFromChildContextThatShouldBeWoven = childAc.getBean("adrian2", ITestBean.class);
assertAspectsAndAdvisorAreApplied(childAc, beanFromParentContextThatShouldBeWoven);
assertAspectsAndAdvisorAreApplied(childAc, beanFromChildContextThatShouldBeWoven);
}

protected void doTestAspectsAndAdvisorAreApplied(ApplicationContext ac, ITestBean shouldBeWeaved) {
protected void assertAspectsAndAdvisorAreApplied(ApplicationContext ac, ITestBean shouldBeWoven) {
TestBeanAdvisor tba = (TestBeanAdvisor) ac.getBean("advisor");

MultiplyReturnValue mrv = (MultiplyReturnValue) ac.getBean("aspect");
Expand All @@ -146,10 +148,10 @@ protected void doTestAspectsAndAdvisorAreApplied(ApplicationContext ac, ITestBea
tba.count = 0;
mrv.invocations = 0;

assertThat(AopUtils.isAopProxy(shouldBeWeaved)).as("Autoproxying must apply from @AspectJ aspect").isTrue();
assertThat(shouldBeWeaved.getName()).isEqualTo("Adrian");
assertThat(AopUtils.isAopProxy(shouldBeWoven)).as("Autoproxying must apply from @AspectJ aspect").isTrue();
assertThat(shouldBeWoven.getName()).isEqualTo("Adrian");
assertThat(mrv.invocations).isEqualTo(0);
assertThat(shouldBeWeaved.getAge()).isEqualTo((34 * mrv.getMultiple()));
assertThat(shouldBeWoven.getAge()).isEqualTo((34 * mrv.getMultiple()));
assertThat(tba.count).as("Spring advisor must be invoked").isEqualTo(2);
assertThat(mrv.invocations).as("Must be able to hold state in aspect").isEqualTo(1);
}
Expand All @@ -158,13 +160,13 @@ protected void doTestAspectsAndAdvisorAreApplied(ApplicationContext ac, ITestBea
void perThisAspect() {
ClassPathXmlApplicationContext bf = newContext("perthis.xml");

ITestBean adrian1 = (ITestBean) bf.getBean("adrian");
ITestBean adrian1 = bf.getBean("adrian", ITestBean.class);
assertThat(AopUtils.isAopProxy(adrian1)).isTrue();

assertThat(adrian1.getAge()).isEqualTo(0);
assertThat(adrian1.getAge()).isEqualTo(1);

ITestBean adrian2 = (ITestBean) bf.getBean("adrian");
ITestBean adrian2 = bf.getBean("adrian", ITestBean.class);
assertThat(adrian2).isNotSameAs(adrian1);
assertThat(AopUtils.isAopProxy(adrian1)).isTrue();
assertThat(adrian2.getAge()).isEqualTo(0);
Expand All @@ -178,7 +180,7 @@ void perThisAspect() {
void perTargetAspect() throws SecurityException, NoSuchMethodException {
ClassPathXmlApplicationContext bf = newContext("pertarget.xml");

ITestBean adrian1 = (ITestBean) bf.getBean("adrian");
ITestBean adrian1 = bf.getBean("adrian", ITestBean.class);
assertThat(AopUtils.isAopProxy(adrian1)).isTrue();

// Does not trigger advice or count
Expand All @@ -199,7 +201,7 @@ void perTargetAspect() throws SecurityException, NoSuchMethodException {
adrian1.setName("Adrian");
//assertEquals("Any other setter does not increment", 2, adrian1.getAge());

ITestBean adrian2 = (ITestBean) bf.getBean("adrian");
ITestBean adrian2 = bf.getBean("adrian", ITestBean.class);
assertThat(adrian2).isNotSameAs(adrian1);
assertThat(AopUtils.isAopProxy(adrian1)).isTrue();
assertThat(adrian2.getAge()).isEqualTo(34);
Expand Down Expand Up @@ -239,17 +241,17 @@ void cglibProxyClassIsCachedAcrossApplicationContextsForPerTargetAspect() {
void twoAdviceAspect() {
ClassPathXmlApplicationContext bf = newContext("twoAdviceAspect.xml");

ITestBean adrian1 = (ITestBean) bf.getBean("adrian");
ITestBean adrian1 = bf.getBean("adrian", ITestBean.class);
testAgeAspect(adrian1, 0, 2);
}

@Test
void twoAdviceAspectSingleton() {
ClassPathXmlApplicationContext bf = newContext("twoAdviceAspectSingleton.xml");

ITestBean adrian1 = (ITestBean) bf.getBean("adrian");
ITestBean adrian1 = bf.getBean("adrian", ITestBean.class);
testAgeAspect(adrian1, 0, 1);
ITestBean adrian2 = (ITestBean) bf.getBean("adrian");
ITestBean adrian2 = bf.getBean("adrian", ITestBean.class);
assertThat(adrian2).isNotSameAs(adrian1);
testAgeAspect(adrian2, 2, 1);
}
Expand All @@ -258,9 +260,9 @@ void twoAdviceAspectSingleton() {
void twoAdviceAspectPrototype() {
ClassPathXmlApplicationContext bf = newContext("twoAdviceAspectPrototype.xml");

ITestBean adrian1 = (ITestBean) bf.getBean("adrian");
ITestBean adrian1 = bf.getBean("adrian", ITestBean.class);
testAgeAspect(adrian1, 0, 1);
ITestBean adrian2 = (ITestBean) bf.getBean("adrian");
ITestBean adrian2 = bf.getBean("adrian", ITestBean.class);
assertThat(adrian2).isNotSameAs(adrian1);
testAgeAspect(adrian2, 0, 1);
}
Expand All @@ -280,7 +282,7 @@ private void testAgeAspect(ITestBean adrian, int start, int increment) {
void adviceUsingJoinPoint() {
ClassPathXmlApplicationContext bf = newContext("usesJoinPointAspect.xml");

ITestBean adrian1 = (ITestBean) bf.getBean("adrian");
ITestBean adrian1 = bf.getBean("adrian", ITestBean.class);
adrian1.getAge();
AdviceUsingThisJoinPoint aspectInstance = (AdviceUsingThisJoinPoint) bf.getBean("aspect");
//(AdviceUsingThisJoinPoint) Aspects.aspectOf(AdviceUsingThisJoinPoint.class);
Expand All @@ -292,7 +294,7 @@ void adviceUsingJoinPoint() {
void includeMechanism() {
ClassPathXmlApplicationContext bf = newContext("usesInclude.xml");

ITestBean adrian = (ITestBean) bf.getBean("adrian");
ITestBean adrian = bf.getBean("adrian", ITestBean.class);
assertThat(AopUtils.isAopProxy(adrian)).isTrue();
assertThat(adrian.getAge()).isEqualTo(68);
}
Expand All @@ -310,7 +312,7 @@ void forceProxyTargetClass() {
void withAbstractFactoryBeanAreApplied() {
ClassPathXmlApplicationContext bf = newContext("aspectsWithAbstractBean.xml");

ITestBean adrian = (ITestBean) bf.getBean("adrian");
ITestBean adrian = bf.getBean("adrian", ITestBean.class);
assertThat(AopUtils.isAopProxy(adrian)).isTrue();
assertThat(adrian.getAge()).isEqualTo(68);
}
Expand All @@ -321,8 +323,7 @@ void retryAspect() {

UnreliableBean bean = (UnreliableBean) bf.getBean("unreliableBean");
RetryAspect aspect = (RetryAspect) bf.getBean("retryAspect");
int attempts = bean.unreliable();
assertThat(attempts).isEqualTo(2);
assertThat(bean.unreliable()).isEqualTo(2);
assertThat(aspect.getBeginCalls()).isEqualTo(2);
assertThat(aspect.getRollbackCalls()).isEqualTo(1);
assertThat(aspect.getCommitCalls()).isEqualTo(1);
Expand All @@ -332,7 +333,7 @@ void retryAspect() {
void withBeanNameAutoProxyCreator() {
ClassPathXmlApplicationContext bf = newContext("withBeanNameAutoProxyCreator.xml");

ITestBean tb = (ITestBean) bf.getBean("adrian");
ITestBean tb = bf.getBean("adrian", ITestBean.class);
assertThat(tb.getAge()).isEqualTo(68);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,59 +56,54 @@
*/
class BeanFactoryTransactionTests {

private DefaultListableBeanFactory factory;
private final DefaultListableBeanFactory factory = new DefaultListableBeanFactory();


@BeforeEach
void setUp() {
this.factory = new DefaultListableBeanFactory();
void loadBeanDefinitions() {
new XmlBeanDefinitionReader(this.factory).loadBeanDefinitions(
new ClassPathResource("transactionalBeanFactory.xml", getClass()));
}


@Test
void testGetsAreNotTransactionalWithProxyFactory1() {
ITestBean testBean = (ITestBean) factory.getBean("proxyFactory1");
void getsAreNotTransactionalWithProxyFactory1() {
ITestBean testBean = factory.getBean("proxyFactory1", ITestBean.class);
assertThat(Proxy.isProxyClass(testBean.getClass())).as("testBean is a dynamic proxy").isTrue();
boolean condition = testBean instanceof TransactionalProxy;
assertThat(condition).isFalse();
doTestGetsAreNotTransactional(testBean);
assertThat(testBean).isNotInstanceOf(TransactionalProxy.class);
assertGetsAreNotTransactional(testBean);
}

@Test
void testGetsAreNotTransactionalWithProxyFactory2DynamicProxy() {
void getsAreNotTransactionalWithProxyFactory2DynamicProxy() {
this.factory.preInstantiateSingletons();
ITestBean testBean = (ITestBean) factory.getBean("proxyFactory2DynamicProxy");
ITestBean testBean = factory.getBean("proxyFactory2DynamicProxy", ITestBean.class);
assertThat(Proxy.isProxyClass(testBean.getClass())).as("testBean is a dynamic proxy").isTrue();
boolean condition = testBean instanceof TransactionalProxy;
assertThat(condition).isTrue();
doTestGetsAreNotTransactional(testBean);
assertThat(testBean).isInstanceOf(TransactionalProxy.class);
assertGetsAreNotTransactional(testBean);
}

@Test
void testGetsAreNotTransactionalWithProxyFactory2Cglib() {
ITestBean testBean = (ITestBean) factory.getBean("proxyFactory2Cglib");
void getsAreNotTransactionalWithProxyFactory2Cglib() {
ITestBean testBean = factory.getBean("proxyFactory2Cglib", ITestBean.class);
assertThat(AopUtils.isCglibProxy(testBean)).as("testBean is CGLIB advised").isTrue();
boolean condition = testBean instanceof TransactionalProxy;
assertThat(condition).isTrue();
doTestGetsAreNotTransactional(testBean);
assertThat(testBean).isInstanceOf(TransactionalProxy.class);
assertGetsAreNotTransactional(testBean);
}

@Test
void testProxyFactory2Lazy() {
ITestBean testBean = (ITestBean) factory.getBean("proxyFactory2Lazy");
void proxyFactory2Lazy() {
ITestBean testBean = factory.getBean("proxyFactory2Lazy", ITestBean.class);
assertThat(factory.containsSingleton("target")).isFalse();
assertThat(testBean.getAge()).isEqualTo(666);
assertThat(factory.containsSingleton("target")).isTrue();
}

@Test
void testCglibTransactionProxyImplementsNoInterfaces() {
ImplementsNoInterfaces ini = (ImplementsNoInterfaces) factory.getBean("cglibNoInterfaces");
void cglibTransactionProxyImplementsNoInterfaces() {
ImplementsNoInterfaces ini = factory.getBean("cglibNoInterfaces", ImplementsNoInterfaces.class);
assertThat(AopUtils.isCglibProxy(ini)).as("testBean is CGLIB advised").isTrue();
boolean condition = ini instanceof TransactionalProxy;
assertThat(condition).isTrue();
assertThat(ini).isInstanceOf(TransactionalProxy.class);
String newName = "Gordon";

// Install facade
Expand All @@ -121,31 +116,41 @@ void testCglibTransactionProxyImplementsNoInterfaces() {
}

@Test
void testGetsAreNotTransactionalWithProxyFactory3() {
ITestBean testBean = (ITestBean) factory.getBean("proxyFactory3");
boolean condition = testBean instanceof DerivedTestBean;
assertThat(condition).as("testBean is a full proxy").isTrue();
boolean condition1 = testBean instanceof TransactionalProxy;
assertThat(condition1).isTrue();
InvocationCounterPointcut txnCounter = (InvocationCounterPointcut) factory.getBean("txnInvocationCounterPointcut");
InvocationCounterInterceptor preCounter = (InvocationCounterInterceptor) factory.getBean("preInvocationCounterInterceptor");
InvocationCounterInterceptor postCounter = (InvocationCounterInterceptor) factory.getBean("postInvocationCounterInterceptor");
txnCounter.counter = 0;
preCounter.counter = 0;
postCounter.counter = 0;
doTestGetsAreNotTransactional(testBean);
// Can't assert it's equal to 4 as the pointcut may be optimized and only invoked once
assertThat(0 < txnCounter.counter && txnCounter.counter <= 4).isTrue();
assertThat(preCounter.counter).isEqualTo(4);
assertThat(postCounter.counter).isEqualTo(4);
void getsAreNotTransactionalWithProxyFactory3() {
ITestBean testBean = factory.getBean("proxyFactory3", ITestBean.class);
assertThat(testBean).as("testBean is a full proxy")
.isInstanceOf(DerivedTestBean.class)
.isInstanceOf(TransactionalProxy.class);

InvocationCounterPointcut txnPointcut = factory.getBean("txnInvocationCounterPointcut", InvocationCounterPointcut.class);
InvocationCounterInterceptor preInterceptor = factory.getBean("preInvocationCounterInterceptor", InvocationCounterInterceptor.class);
InvocationCounterInterceptor postInterceptor = factory.getBean("postInvocationCounterInterceptor", InvocationCounterInterceptor.class);
assertThat(txnPointcut.counter).as("txnPointcut").isGreaterThan(0);
assertThat(preInterceptor.counter).as("preInterceptor").isZero();
assertThat(postInterceptor.counter).as("postInterceptor").isZero();

// Reset counters
txnPointcut.counter = 0;
preInterceptor.counter = 0;
postInterceptor.counter = 0;

// Invokes: getAge() * 2 and setAge() * 1 --> 2 + 1 = 3 method invocations.
assertGetsAreNotTransactional(testBean);

// The transaction pointcut is currently asked if it matches() for all method
// invocations, but we cannot assert it's equal to 3 since the pointcut may be
// optimized and only invoked once.
assertThat(txnPointcut.counter).as("txnPointcut").isGreaterThanOrEqualTo(1).isLessThanOrEqualTo(3);
assertThat(preInterceptor.counter).as("preInterceptor").isEqualTo(3);
assertThat(postInterceptor.counter).as("postInterceptor").isEqualTo(3);
}

private void doTestGetsAreNotTransactional(final ITestBean testBean) {
private void assertGetsAreNotTransactional(final ITestBean testBean) {
// Install facade
PlatformTransactionManager ptm = mock();
PlatformTransactionManagerFacade.delegate = ptm;

assertThat(testBean.getAge()).as("Age should not be " + testBean.getAge()).isEqualTo(666);
assertThat(testBean.getAge()).as("Age").isEqualTo(666);

// Expect no methods
verifyNoInteractions(ptm);
Expand Down Expand Up @@ -177,14 +182,14 @@ public void rollback(TransactionStatus status) throws TransactionException {
};
PlatformTransactionManagerFacade.delegate = ptm;

// TODO same as old age to avoid ordering effect for now
// same as old age to avoid ordering effect for now
int age = 666;
testBean.setAge(age);
assertThat(testBean.getAge()).isEqualTo(age);
}

@Test
void testGetBeansOfTypeWithAbstract() {
void getBeansOfTypeWithAbstract() {
Map<String, ITestBean> beansOfType = factory.getBeansOfType(ITestBean.class, true, true);
assertThat(beansOfType).isNotNull();
}
Expand All @@ -193,32 +198,30 @@ void testGetBeansOfTypeWithAbstract() {
* Check that we fail gracefully if the user doesn't set any transaction attributes.
*/
@Test
void testNoTransactionAttributeSource() {
assertThatExceptionOfType(FatalBeanException.class).isThrownBy(() -> {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(new ClassPathResource("noTransactionAttributeSource.xml", getClass()));
bf.getBean("noTransactionAttributeSource");
});
void noTransactionAttributeSource() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(new ClassPathResource("noTransactionAttributeSource.xml", getClass()));
assertThatExceptionOfType(FatalBeanException.class).isThrownBy(() -> bf.getBean("noTransactionAttributeSource"));
}

/**
* Test that we can set the target to a dynamic TargetSource.
*/
@Test
void testDynamicTargetSource() {
void dynamicTargetSource() {
// Install facade
CallCountingTransactionManager txMan = new CallCountingTransactionManager();
PlatformTransactionManagerFacade.delegate = txMan;

TestBean tb = (TestBean) factory.getBean("hotSwapped");
TestBean tb = factory.getBean("hotSwapped", TestBean.class);
assertThat(tb.getAge()).isEqualTo(666);
int newAge = 557;
tb.setAge(newAge);
assertThat(tb.getAge()).isEqualTo(newAge);

TestBean target2 = new TestBean();
target2.setAge(65);
HotSwappableTargetSource ts = (HotSwappableTargetSource) factory.getBean("swapper");
HotSwappableTargetSource ts = factory.getBean("swapper", HotSwappableTargetSource.class);
ts.swap(target2);
assertThat(tb.getAge()).isEqualTo(target2.getAge());
tb.setAge(newAge);
Expand Down

0 comments on commit 172c8b2

Please sign in to comment.