Skip to content

Instantly share code, notes, and snippets.

@zkendall
Last active August 3, 2016 02:25
Show Gist options
  • Save zkendall/b42f0a86418b6329163ab06f366264d4 to your computer and use it in GitHub Desktop.
Save zkendall/b42f0a86418b6329163ab06f366264d4 to your computer and use it in GitHub Desktop.
Test to demonstrate incorrect behavior when trying to verify the behavior of a spy on already proxied instance.
/*
Relevant dependencies:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.2.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.0.91-beta</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.5.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.9.10</version>
<scope>test</scope>
</dependency>
*/
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.aop.aspectj.annotation.AspectJProxyFactory;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import static org.mockito.Mockito.*;
public class VerifySpyProxyTest {
private TestSubject proxy;
@BeforeClass
public void setupProxySpy() {
final TestSubject testSubject = new TestSubject();
// If you try to spy before giving to factory, you get a ClassCastException.
AspectJProxyFactory factory = new AspectJProxyFactory(testSubject);
// NOTE: This aspect is optional. Incorrect behavior happens even if no methods annotated or no aspect
// definitions are provided to factory..
factory.addAspect(new ExampleAspect());
proxy = factory.getProxy();
proxy = spy(proxy);
}
@BeforeMethod(enabled = false, description = "reset() FAILS with proxy but works on plain spy.")
public void resetMocks() {
reset(proxy);
}
@Test
public void testSpyOnProxy_1() {
proxy.doWork();
verify(proxy, times(1)).doWork();
// Console shows doWork() and doAspect() called 2 times.
}
@Test(description = "Works when run alone, but fails when run as suite after testSpyOnProxy_1")
public void testSpyOnProxy_55() {
proxy.doWork();
verify(proxy, times(55)).doWork();
// Console shows doWork() and doAspect() called 1 time and then UnfinishedVerificationException.
}
@Test
public void testSpyOnProxy_never() {
proxy.doWork();
verify(proxy, never()).doWork();
// Console shows doWork() and doAspect() called 2 times.
}
/**
* Example AOP proxy subject.
*/
public class TestSubject {
@ExampleAnnotation
public void doWork() {
System.out.println("doWork() was called");
}
}
/**
* Example annotation used for aspect.
*/
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(value = RetentionPolicy.RUNTIME)
public @interface ExampleAnnotation {
}
/**
* Example aspect handler.
*/
@Aspect
public class ExampleAspect {
@Around("@annotation( annotation )")
public Object doAspect(final ProceedingJoinPoint pjp, ExampleAnnotation annotation)
throws Throwable {
System.out.println("doAspect() was called");
return pjp.proceed();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment