0

I am struggling to write unit test cases for aspect code. Please find the all the respective code.

Custom Annotation -

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface WriteAccessAuthorization{
  boolean isAdmin() default false;
}

Aspect Code -

  @Aspect
  class AccessAspect {
  ...
  ...
    boolean isAdminForWriteAccess(ProceedingJoinPoint joinPoint) {
      MethodSignature signature = (MethodSignature) joinPoint.getSignature();
      Method method = signature.getMethod();
      WriteAccessAuthorization writeAccessAuthorization =
          method.getAnnotation(WriteAccessAuthorization.class);
      return writeAccessAuthorization.isAdminPortal();
    }
  ...
  }

Here I am getting NPE in last line of the method. Here method.getAnnotation() is returning null even we are mocking it in Junit test method.

Please find the junit test case code -

class AccessAspectTest {
  @Mock private ProceedingJoinPoint joinPoint;
  @Mock private MethodSignature methodSignature;
  @Mock private Method method;
  @Mock private WriteAccessAuthorization writeAccessAuthorization;
  @InjectMocks private AccessAspect accessAspect;

  @BeforeEach
  public void setup() {
    MockitoAnnotations.openMocks(this);
  }

  @Test
  void test_isAdmin()
      throws Throwable {
    //Given
    when(joinPoint.getSignature()).thenReturn(methodSignature);
    when(methodSignature.getMethod()).thenReturn(getDeclaredMethod(WriteAccessAuthorization.class));
    when(method.getAnnotation(WriteAccessAuthorization.class)).thenReturn(writeAccessAuthorization);

    //When
    accessAspect.isAdminForWriteAccess(joinPoint);
    
    //Then
    verify(joinPoint, times(1)).proceed();
  }

  @NotNull
  private <T> Method getDeclaredMethod(Class<T> clazz) throws NoSuchMethodException {
    return clazz.getDeclaredMethod("isAdmin");
  }

}

In many blogs or stackoverflow answers it was mention to have RUNTIME policy in you annotation but in my case it was already placed. Please let me know if there is anything else required.

Nitesh Sharma
  • 545
  • 3
  • 14
  • It is really counter-productive to replace important parts of your sample code by "...". You want to test an aspect, but are omitting the pointcut and advice. Please learn what an [MCVE](https://stackoverflow.com/help/mcve) is and how it helps you to get the answers you are asking for here, enabling your helpers to understand and reproduce the actual problem without speculating what might be behind "...". This is not a quiz show, this is Stack Overflow. Developers want to analyse, not to guess. – kriegaex Oct 03 '22 at 09:01
  • A basic example how to unit-test an aspect is [here](https://stackoverflow.com/a/41407336/1082681). Integration-testing the same code is described [here](https://stackoverflow.com/q/41446622/1082681). I can write a more precise answer once you provide an MCVE. Please do not forget to add the code under test to the MCVE, too. It should be "M" (minimal), but still "C" (complete). – kriegaex Oct 03 '22 at 09:09

1 Answers1

0

You actually need to apply the annotation to a method. What your code is testing is whether the isAdmin method defined in annotation interface is annotated with WriteAccessAuthorization which it is not. That's why method.getAnnotation returns null.

Here is an example of how to access the annotation:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface WriteAccessAuthorization {
    boolean isAdmin() default false;
}


public static final class SomeClass {
    @WriteAccessAuthorization
    public void doSth() {}
}

public static void main(String[] args) throws Exception {
    Method method = SomeClass.class.getDeclaredMethod("doSth");
    WriteAccessAuthorization annotation =
            method.getDeclaredAnnotation(WriteAccessAuthorization.class);
    System.out.println(annotation);
}

Output:

@com.example.test$WriteAccessAuthorization(isAdmin=false)
Alex R
  • 3,139
  • 1
  • 18
  • 28