TracklyticsAspect { @Around("methodAnnotatedWithTrackEvent() || constructorAnnotatedTrackEvent()") public Object weaveJoinPointTrackEvent(ProceedingJoinPoint joinPoint) throws Throwable { Object result = joinPoint.proceed(); final Map<String, Object> attributes = new HashMap<>(); Method method = ((MethodSignature) joinPoint.getSignature()).getMethod(); addClassAttributes(method, joinPoint, attributes); Map<Integer, String> transformMap = new HashMap<>(); addMethodAttributes(method, result, attributes, transformMap); addMethodParameterAttributes(method, joinPoint, attributes, transformMap); TrackEvent trackEvent = method.getAnnotation(TrackEvent.class); pushEvent(trackEvent, attributes); return result; }  @Pointcut("execution(@com.orhanobut.tracklytics.TrackSuperAttribute * *(..))") void methodAnnotatedWithSuperAttribute(); @Pointcut("execution(@com.orhanobut.tracklytics.TrackSuperAttribute *.new(..))") void constructorAnnotatedWithSuperAttribute(); @Around("methodAnnotatedWithSuperAttribute() || constructorAnnotatedWithSuperAttribute()") void weaveJoinPointSuperAttribute(ProceedingJoinPoint joinPoint); @Pointcut("execution(@com.orhanobut.tracklytics.RemoveSuperAttribute * *(..))") void methodAnnotatedWithRemoveSuperAttribute(); @Pointcut("execution(@com.orhanobut.tracklytics.RemoveSuperAttribute *.new(..))") void constructorAnnotatedWithRemoveSuperAttribute(); @Around("methodAnnotatedWithRemoveSuperAttribute() || constructorAnnotatedWithRemoveSuperAttribute()") void weaveJoinPointRemoveSuperAttribute(ProceedingJoinPoint joinPoint); @Pointcut("execution(@com.orhanobut.tracklytics.TrackEvent * *(..))") void methodAnnotatedWithTrackEvent(); @Pointcut("execution(@com.orhanobut.tracklytics.TrackEvent *.new(..))") void constructorAnnotatedTrackEvent(); @Around("methodAnnotatedWithTrackEvent() || constructorAnnotatedTrackEvent()") Object weaveJoinPointTrackEvent(ProceedingJoinPoint joinPoint);  }
@Test public void methodParameterWithoutAnnotation() throws Throwable { class Foo { @TrackEvent("title") public void foo(@Attribute("Key") String bar, String param2) { } } when(joinPoint.getArgs()).thenReturn(new Object[]{"sdfsd"}); invokeMethod(Foo.class, "foo", String.class, String.class); try { aspect.weaveJoinPointTrackEvent(joinPoint); } catch (Exception e) { fail("Method parameters without annotation should be accepted"); } }
@Test public void trackableAttributeForCurrentClass() throws Throwable { class Foo implements Trackable { @Override public Map<String, Object> getTrackableAttributes() { Map<String, Object> map = new HashMap<>(); map.put("key", "value"); return map; } @TrackEvent("event") @TrackableAttribute public void foo() { } } initMethod(Foo.class, "foo"); when(joinPoint.getThis()).thenReturn(new Foo()); aspect.weaveJoinPointTrackEvent(joinPoint); assertTrack() .event("event") .noFilters() .noTags() .attribute("key", "value"); }
@Test public void ignoreNullValueOnTrackableAttributeForCurrentClass() throws Throwable { class Foo implements Trackable { @Override public Map<String, Object> getTrackableAttributes() { return null; } @TrackEvent("event") @TrackableAttribute public void foo() { } } initMethod(Foo.class, "foo"); when(joinPoint.getThis()).thenReturn(new Foo()); aspect.weaveJoinPointTrackEvent(joinPoint); assertTrack() .event("event") .noFilters() .noTags() .noAttributes(); }
@Test public void useThisClassWhenCalledFromSuperClass() throws Throwable { @FixedAttribute(key = "key0", value = "value0") class Base { @TrackEvent("event") public void base() { } } @FixedAttribute(key = "key", value = "value") @FixedAttributes( @FixedAttribute(key = "key2", value = "value2") ) class Foo extends Base { } initMethod(Foo.class, "base"); when(joinPoint.getThis()).thenReturn(new Foo()); aspect.weaveJoinPointTrackEvent(joinPoint); assertTrack() .event("event") .noFilters() .noTags() .attribute("key0", "value0") .attribute("key", "value") .attribute("key2", "value2"); }