Last active
August 3, 2016 02:25
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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