Hot questions for Using Mockito in aspectj
Question:
I am trying to write Junit tests for Custom Aspect. Here is the Aspect Class Snippet:
@Aspect @Component public class SampleAspect { private static Logger log = LoggerFactory.getLogger(SampleAspect.class); @Around("execution(* org.springframework.data.mongodb.core.MongoOperations.*(..)) || execution(* org.springframework.web.client.RestOperations.*(..))") public Object intercept(final ProceedingJoinPoint point) throws Throwable { logger.info("invoked Cutom aspect"); return point.proceed(); } }
So the above aspect intercepts whenever jointpoint matches the pointcut. Its working fine.
But my question is how to unit test that class. I have the following Junit Test:
@Test(expected = MongoTimeoutException.class) public void TestWithMongoTemplate() { //MongoDocument class TestDocument test = new TestDocument(); ApplicationContext ctx = new AnnotationConfigApplicationContext(TestMongoConfigurationMain.class); MongoTemplate mongoTemplate = ctx.getBean(MongoTemplate.class); //this call is being intercepted by SampleAspect mongoTemplate.save(test); }
So my mongoTemplate.save(test)
in Junit is being intercepted by SampleAspect
as it matches pointcut. But how should I make sure in junits(probably by asserting) that my SampleAspect
is intercepting when that joint point is invoked?
I cannot assert on return value from intercept()
as it does nothing special other than executing joint point. So my Junit cannot find any difference whether its being executed by aspect or a regular execution based on return values.
Any code snippets examples on aspect testing would be great if provided.Thanks
Answer:
I think what you are trying to test is aspect weaving and pointcut matching. Please note that that would be an integration rather than a unit test. If you really want to unit test your aspect logic and because you have tagged the question by "mockito" anyway, I suggest you do just that: Write a unit test and mock the aspect's joinpoint and maybe its other parameters, if any. Here is a slightly more complex example with some intra-aspect logic:
Java class to be targeted by aspect:
package de.scrum_master.app; public class Application { public static void main(String[] args) { new Application().doSomething(11); new Application().doSomething(-22); new Application().doSomething(333); } public void doSomething(int number) { System.out.println("Doing something with number " + number); } }
Aspect under test:
package de.scrum_master.aspect; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; @Aspect public class SampleAspect { @Around("execution(* doSomething(int)) && args(number)") public Object intercept(final ProceedingJoinPoint thisJoinPoint, int number) throws Throwable { System.out.println(thisJoinPoint + " -> " + number); if (number < 0) return thisJoinPoint.proceed(new Object[] { -number }); if (number > 99) throw new RuntimeException("oops"); return thisJoinPoint.proceed(); } }
Console log when running Application.main(..)
:
As you can see, the aspect passes on 11, negates -22 and throws an exception for 333:
execution(void de.scrum_master.app.Application.doSomething(int)) -> 11 Doing something with number 11 execution(void de.scrum_master.app.Application.doSomething(int)) -> -22 Doing something with number 22 execution(void de.scrum_master.app.Application.doSomething(int)) -> 333 Exception in thread "main" java.lang.RuntimeException: oops at de.scrum_master.aspect.SampleAspect.intercept(SampleAspect.aj:15) at de.scrum_master.app.Application.doSomething(Application.java:10) at de.scrum_master.app.Application.main(Application.java:7)
Unit test for aspect:
Now we really want to verify that the aspect does what it should and cover all execution paths:
package de.scrum_master.aspect; import org.aspectj.lang.ProceedingJoinPoint; import org.junit.Rule; import org.junit.Test; import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import static org.mockito.Mockito.*; public class SampleAspectTest { @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); @Mock private ProceedingJoinPoint proceedingJoinPoint; private SampleAspect sampleAspect = new SampleAspect(); @Test public void testPositiveSmallNumber() throws Throwable { sampleAspect.intercept(proceedingJoinPoint, 11); // 'proceed()' is called exactly once verify(proceedingJoinPoint, times(1)).proceed(); // 'proceed(Object[])' is never called verify(proceedingJoinPoint, never()).proceed(null); } @Test public void testNegativeNumber() throws Throwable { sampleAspect.intercept(proceedingJoinPoint, -22); // 'proceed()' is never called verify(proceedingJoinPoint, never()).proceed(); // 'proceed(Object[])' is called exactly once verify(proceedingJoinPoint, times(1)).proceed(new Object[] { 22 }); } @Test(expected = RuntimeException.class) public void testPositiveLargeNumber() throws Throwable { sampleAspect.intercept(proceedingJoinPoint, 333); } }
Now run this simple JUnit + Mockito test in order to test the aspect logic in isolation, not the wiring/weaving logic. For the latter you would need another type of test.
P.S.: Only for you I used JUnit and Mockito. Usually I just use Spock and its built-in mocking capabilities. ;-)
Question:
I am trying to write Integratation tests for Custom Aspect. Here is the Aspect Class Snippet.
@Aspect @Component public class SampleAspect { private static Logger log = LoggerFactory.getLogger(SampleAspect.class); private int count; public int getCount(){ return count; } public void setCount(){ this.count= count; } @Around("execution(* org.springframework.data.mongodb.core.MongoOperations.*(..)) || execution(* org.springframework.web.client.RestOperations.*(..))") public Object intercept(final ProceedingJoinPoint point) throws Throwable { logger.info("invoked Cutom aspect"); setCount(1); return point.proceed(); } }
So the above aspect intercepts whenever jointpoint matches the pointcut. Its working fine. But my question is how to perform Integration test.
What I have done is I created the attribute "count" in Aspect for tracking and asserted it in my Junit. I am not sure if this is good or is there a better way of doing integration testing on aspects.
Here is the snippet of Junit what I have done. I presented in bad way but I hope its undestandable of what I have done for Integration testing.
@Test public void testSamepleAspect(){ sampleAspect.intercept(mockJointPoint); Assert.assertEquals(simpleAspect.getCount(),1); }
Answer:
Let us use the same sample code as in my answer to the related AspectJ unit testing question:
Java class to be targeted by aspect:
package de.scrum_master.app; public class Application { public void doSomething(int number) { System.out.println("Doing something with number " + number); } }
Aspect under test:
package de.scrum_master.aspect; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; @Aspect public class SampleAspect { @Around("execution(* doSomething(int)) && args(number)") public Object intercept(final ProceedingJoinPoint thisJoinPoint, int number) throws Throwable { System.out.println(thisJoinPoint + " -> " + number); if (number < 0) return thisJoinPoint.proceed(new Object[] { -number }); if (number > 99) throw new RuntimeException("oops"); return thisJoinPoint.proceed(); } }
You have several options, depending on what exactly you want to test:
- You can run the AspectJ compiler and verify its console output (with weaving info enabled) in order to make sure that the expected joinpoints are actually woven and others are not. But this would rather be a test for your AspectJ configuration and the build process as such than a real integration test.
- Similarly, you can create a new weaving classloader, load the aspect and then a few classes (load-time weaving, LTW) in order to dynamically check what gets woven and what does not. In this case you are rather testing if your pointcuts are correct than the integrated application consisting of core + aspect code.
- Last, but not least, you can perform a normal integration test, assuming how the application should behave after core + aspect code have been woven correctly. How to do this depends on you concrete situation, specifically on what kind of side effect your aspect adds to the core code.
Subsequently I will describe option no. 3. Looking at the sample code above, we see the following side effects:
- For small positive numbers the aspect passes through the original parameter value to the intercepted method, the only side effect being additional log output.
- For negative numbers the aspect passes through the negated parameter value (e.g. turning -22 into 22) to the intercepted method, which is nicely testable.
- For larger positive numbers the aspect throws an exception, effectively stopping the original method from being executed at all.
Integration test for aspect:
package de.scrum_master.aspect; import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.matches; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import java.io.PrintStream; import org.junit.*; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import de.scrum_master.app.Application; public class SampleAspectIT { @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); private Application application = new Application(); private PrintStream originalSystemOut; @Mock private PrintStream fakeSystemOut; @Before public void setUp() throws Exception { originalSystemOut = System.out; System.setOut(fakeSystemOut); } @After public void tearDown() throws Exception { System.setOut(originalSystemOut); } @Test public void testPositiveSmallNumber() throws Throwable { application.doSomething(11); verify(System.out, times(1)).println(matches("execution.*doSomething.* 11")); verify(System.out, times(1)).println(matches("Doing something with number 11")); } @Test public void testNegativeNumber() throws Throwable { application.doSomething(-22); verify(System.out, times(1)).println(matches("execution.*doSomething.* -22")); verify(System.out, times(1)).println(matches("Doing something with number 22")); } @Test(expected = RuntimeException.class) public void testPositiveLargeNumber() throws Throwable { try { application.doSomething(333); } catch (Exception e) { verify(System.out, times(1)).println(matches("execution.*doSomething.* 333")); verify(System.out, times(0)).println(matches("Doing something with number")); assertEquals("oops", e.getMessage()); throw e; } } }
Et voilĂ , we are testing exactly the three types of side effects our sample aspect has by inspecting log output to a mock instance of System.out
and by making sure that the expected exception is thrown for larger positive numbers.
Question:
I have a Spring MVC application where I use an Aspect to catch exceptions in all controller methods
@Component @Aspect public class ControllerExceptionAspect { private Logger logger; public ControllerExceptionAspect() { logger = Logger.getLogger(ControllerExceptionAspect.class); } public ControllerExceptionAspect(Logger logger) { this.logger = logger; } // Catching all exceptions from all methods in all controllers classes @AfterThrowing(pointcut = "execution(* com.my.package..controller..*(..))", throwing = "exception") public void afterThrowingAdvice(Exception exception) { logger.error("CONTROLLER ASPECT: EXCEPTION IN METHOD -> " + exception.getClass()); } }
Aspect works fine but unfortunatelly I can not test it. I tried many times but can not get how to catch whether an Aspect method was called after I simulate exception in Controller
@SuppressWarnings("ALL") @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextHierarchy({ @ContextConfiguration(classes = RootConfig.class), @ContextConfiguration(classes = WebConfig.class) }) public class ControllerExceptionAspectTest { @Autowired ApplicationContext applicationContext; @Test public void testControllerExceptionAspectGetsExecutedWhenExceptionOccures(){ HomeController homeController = (HomeController)applicationContext.getAutowireCapableBeanFactory().getBean("homeController"); try{homeController.callMethod("00000");} catch (Exception e){} ControllerExceptionAspect controllerExceptionAspect = (ControllerExceptionAspect)applicationContext.getAutowireCapableBeanFactory().getBean("controllerExceptionAspect"); // HOW TO CATCH THAT ASPECT METHOD WAS CALLED??? } }
Answer:
I think that what you're trying to achieve is testing the configuration which you created (aspects pointcut), rather than aspect itself which could be unit tested. What I'm afraid is that there's no simple way of achieving that.
You could follow some internet advices on catching logs or other ideas. Honestly I'd test the expected behavior of the Aspect only if you really need to test that it was invoked. If it's loging I wouldn't do it. If it's setting something to the db (or other side effect) I'd verify if the value is in the db. That's the sloppy ground of integration testing.
If you really, really must test the aspect the way you want, you can write something similar the given code. But remember that normal (not-test) runtime spring configuration would require a dummy implementation of Verifier interface existing in the Spring context.
@RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(Config.class) public class AspectTesting { @Autowired ServiceWithAspect service; @Autowired Verifier verifyingAspect; @Test public void test() { // given boolean condition = false; // when try { service.doit(); } catch (Exception swallow) {} // then try { condition = ((VerifyingAspect) ((Advised) verifyingAspect).getTargetSource().getTarget()).wasExecuted(); } catch (Exception swallow) {} // then Assert.assertTrue(condition); } } @Configuration @EnableAspectJAutoProxy @ComponentScan("aspects") class Config { } @Component class VerifyingAspect implements Verifier { private boolean executed = false; public boolean wasExecuted() { return executed; } @Override public void invoked() { executed = true; } } @Service class ServiceWithAspect { public void doit() { throw new RuntimeException(); } } @Component @Aspect class TestedAspect { @Autowired Verifier verifier; @AfterThrowing(pointcut = "execution(* *(..))", throwing = "exception") public void afterThrowingAdvice(Exception exception) { // your aspect logic here verifier.invoked(); } } interface Verifier { void invoked(); }
Question:
Background
A project uses Aspects for logging. The particulars:
- Java 11
- AspectJ 1.9.4 (runtime, tools, compiler, post-compile-weaving plugin)
- Mockito Core 2.25.1
The build.gradle
file resembles:
apply plugin: "io.freefair.aspectj.post-compile-weaving" dependencies { compileOnly group: 'javax.servlet', name: 'javax.servlet-api', version: '4.0.1' compileOnly group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.12.1' compileOnly group: 'org.osgi', name: 'org.osgi.framework', version: '1.9.0' compileOnly group: 'org.mockito', name: 'mockito-core', version: '2.25.1' inpath project(":company.project.main") }
Problem
When the application is compiled, AspectJ cannot find MockMethodDispatcher
, and reports an error:
.../mockito-core-2.25.1.jar [error] can't determine superclass of missing type org.mockito.internal.creation.bytebuddy.inject.MockMethodDispatcher when weaving type org.mockito.internal.creation.bytebuddy.MockMethodAdvice when weaving classes when weaving when batch building BuildConfig[null] #Files=0 AopXmls=#0 [Xlint:cantFindType] (no source information available) [Xlint:cantFindType] .../org.mockito/mockito-core/2.25.1/e8fa2864b65c0b6fbb20daa436a94853bcd17e5e/mockito-core-2.25.1.jar [warning] can't find type org.mockito.internal.creation.bytebuddy.inject.MockMethodDispatcher whilst determining signatures of call or execution join point for java.util.concurrent.Callable org.mockito.internal.creation.bytebuddy.MockMethodAdvice.handle(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]), this may cause a pointcut to fail to match at this join point when weaving type org.mockito.internal.creation.bytebuddy.MockMethodAdvice when weaving classes when weaving when batch building BuildConfig[null] #Files=0 AopXmls=#0 [Xlint:cantFindTypeAffectingJPMatch]
I suspect this is because the file is stored as a .raw
file rather than a .class
file (as per issue 845):
1778 Mon Jul 08 13:47:02 PDT 2019 org/mockito/internal/creation/bytebuddy/inject/MockMethodDispatcher.raw
Question
How would you update the Gradle file to instruct the post-compile-weaving plugin to ignore weaving (or scanning) Mockito classes altogether?
Notes
From the command-line, weaving appears to work:
java -cp aspectjtools-1.9.4.jar:aspectjrt-1.9.4.jar org.aspectj.tools.ajc.Main \ -inpath application.jar \ -aspectpath ../aspects/build/classes/java/main \ -Xlint:warning \ -verbose \ -showWeaveInfo \ -log aop.log \ -outjar woven.jar
Though the output classes in woven.jar
should be injected into application.jar
.
Addendum
Note:
- Working around the issue by adorning the
@Aspect
-annotated class with a!within
@Pointcut
annotation is not viable. Would strongly prefer to pass an argument toajc
via the plugin. - Downgrading
cantFindType
from an error to a warning would be a satisfactory answer, but not ideal (stuck on syntax), as I'd like othercantFindType
errors to remain as errors.
Related
- Gradle and AspectJ - avoid weaving my own packages during compile time
- How to set "-aspectpath" for the FreeFair AspectJ Gradle Plugin?
- AspectJ + Gradle configuration
Attempts
When calling compileJava
as follows:
compileJava { ajc { enabled = true classpath = configurations.aspectj options { aspectpath = configurations.aspect compilerArgs = [""] } } }
Gradle reports the following error:
Cannot set the value of read-only property 'classpath' for object of type
io.freefair.gradle.plugins.aspectj.AjcAction
.
Using:
compileJava { ajc { options { compilerArgs = [""] } } }
Gradle reports:
Could not find method options() for arguments [...] on object of type
io.freefair.gradle.plugins.aspectj.AjcAction
.
The source code on master seems to expose different names for its "configurable things":
task.getInputs().property("ajcArgs", this.getOptions().getCompilerArgs())
Answer:
The declared dependency is transitive:
inpath project(":company.project.main")
This will pass the complete runtime classpath of :company.project.main
(the classes produced by said project and all its dependencies) into the -inpath
of ajc. (See the build/tmp/compileJava/ajc.options
file to confirm.)
To avoid weaving advices into external classes, declare a non-transitive dependency as follows:
inpath(project(":company.project.main")) { transitive = false }
Depending on your exact requirements and your project structure, it might be a better approach to apply the io.freefair.aspectj.post-compile-weaving
plugin directly to the :company.project.main
project.
Question:
I have the following test class and I'm using Mockito's spy. By running my unit test using Eclipse (right click->Run as unit test) all tests pass which means that eclipse build process using m2e and AJDT works fine.
@RunWith(MockitoJUnitRunner.class) public class SampleTest { @Mock private AnotherClazz mockedClazz; @Spy @InjectMocks private SampleImpl sampleService = new SampleImpl() { @Override public void someMethod() { ... } }; @Test public void someTest() throws Exception { sampleService.methodUnderTest(); }
However when I use maven to run the tests I get the following exception.
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.183 sec <<< FAILURE! org.sample.SampleTest Time elapsed: 0.182 sec <<< ERROR! org.mockito.exceptions.base.MockitoException: Problems initiating spied field sampleService at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl$1.withBefores(JUnit45AndHigherRunnerImpl.java:27) at org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:254) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) at org.junit.runners.ParentRunner.run(ParentRunner.java:309) at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37) at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62) at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252) at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141) at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189) at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165) at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85) at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115) at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75) Caused by: org.mockito.exceptions.base.MockitoException: Mockito cannot mock this class: class org.sample.SamplelTest$1 Mockito can only mock visible & non-final classes. If you're not sure why you're getting this error, please report to the mailing list. ... 25 more Caused by: org.mockito.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null at org.mockito.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:238) at org.mockito.cglib.proxy.Enhancer.createHelper(Enhancer.java:378) at org.mockito.cglib.proxy.Enhancer.createClass(Enhancer.java:318) at org.mockito.internal.creation.cglib.ClassImposterizer.createProxyClass(ClassImposterizer.java:123) at org.mockito.internal.creation.cglib.ClassImposterizer.imposterise(ClassImposterizer.java:57) at org.mockito.internal.creation.cglib.ClassImposterizer.imposterise(ClassImposterizer.java:49) at org.mockito.internal.creation.cglib.CglibMockMaker.createMock(CglibMockMaker.java:24) at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:33) at org.mockito.internal.MockitoCore.mock(MockitoCore.java:59) at org.mockito.Mockito.mock(Mockito.java:1285) at org.mockito.internal.configuration.injection.SpyOnInjectedFieldsHandler.processInjection(SpyOnInjectedFieldsHandler.java:43) at org.mockito.internal.configuration.injection.MockInjectionStrategy.process(MockInjectionStrategy.java:68) at org.mockito.internal.configuration.injection.MockInjectionStrategy.relayProcessToNextStrategy(MockInjectionStrategy.java:89) at org.mockito.internal.configuration.injection.MockInjectionStrategy.process(MockInjectionStrategy.java:71) at org.mockito.internal.configuration.injection.MockInjection$OngoingMockInjection.apply(MockInjection.java:93) at org.mockito.internal.configuration.DefaultInjectionEngine.injectMocksOnFields(DefaultInjectionEngine.java:20) at org.mockito.internal.configuration.InjectingAnnotationEngine.injectMocks(InjectingAnnotationEngine.java:100) at org.mockito.internal.configuration.InjectingAnnotationEngine.processInjectMocks(InjectingAnnotationEngine.java:62) at org.mockito.internal.configuration.InjectingAnnotationEngine.process(InjectingAnnotationEngine.java:56) at org.mockito.MockitoAnnotations.initMocks(MockitoAnnotations.java:108) ... 25 more Caused by: java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.mockito.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:385) at org.mockito.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:220) ... 44 more Caused by: java.lang.VerifyError: Cannot inherit from final class at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:800) ... 50 more
What is here the difference between the AJC compiler used in Eclipse with AJDT and my AspectJ maven plugin configuration? Which configuration or phase am I missing here?
Here is my pom.xml:
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.6.11</version> </dependency> <build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>1.4</version> <configuration> <source>1.6</source> <target>1.6</target> </configuration> <executions> <execution> <phase>process-sources</phase> <goals> <goal>compile</goal> <goal>test-compile</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
Update: I haven't found a solution yet but I know why is this happening. The problem actually lies here on overriding the someMethod(). Removing the method override or commenting out the aspectj maven plugin solves the problem as a workaround. I cannot let AspectJ out of my project so I have to mock the someMethod() as well without overriding it (e.g. using Mockito itself). It looks like a bug for me but I'm not quite sure does it come from AspectJ or Mockito.
Answer:
What is here the difference between the AJC compiler used in Eclipse with AJDT and my AspectJ maven plugin configuration?
Well, you use a very old AspectJ compiler and runtime from 2011 in Maven, but your AJDT probably uses a much more recent version. BTW, does your code really have to be compliant to Java 6? Anyway, that should not be a problem, but I recommend to use the current AspectJ Maven Plugin 1.7 and also the latest AspectJ version. You can still compile 1.6-compatible code with it. When I tried to recreate your situation with the old AspectJ version, the code would not even compile, but you have not provided a real SSCCE, so I have no idea about your JDK version, Mockito version, JUnit version etc.
Try this Maven configuration in your POM:
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.6</java.version> <aspectj.version>1.8.6</aspectj.version> </properties> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.3</version> <configuration> <source>${java.version}</source> <target>${java.version}</target> <!-- IMPORTANT --> <useIncrementalCompilation>false</useIncrementalCompilation> </configuration> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>1.7</version> <configuration> <showWeaveInfo>true</showWeaveInfo> <source>${java.version}</source> <target>${java.version}</target> <Xlint>ignore</Xlint> <complianceLevel>${java.version}</complianceLevel> <encoding>UTF-8</encoding> <verbose>true</verbose> </configuration> <executions> <execution> <!-- IMPORTANT --> <phase>process-sources</phase> <goals> <goal>compile</goal> <goal>test-compile</goal> </goals> </execution> </executions> <dependencies> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjtools</artifactId> <version>${aspectj.version}</version> </dependency> </dependencies> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>${aspectj.version}</version> <scope>runtime</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>1.9.5</version> <scope>test</scope> </dependency> </dependencies>
This works for me. BTW, please note the <complianceLevel>
in addition to <source>
and <target>
.