Spring beginner here.
I am making two custom annotations @Satisfy and @Verify, meant to be used to track requirements in code.
- @Satisfy denotes where the requirement is implemented
- @Verify denotes where the requirement is tested, e.g. in a junit test case
Each of them have a corresponding @Aspect, which in this snippet just prints a message, but in reality they are used to POST update to gitlab API in order to label requirement issues in gitlab as "satisfied" or "verified".
The @Satisfy aspect is working, it is annotated in the class which implements the required code e.g. the class Addition.
The @Verify aspect is not being called from the JUnit @Test case, as I don't know how to do this. I spent the entire day googling for solutions, and i suspect that aspects might not be able to be used in test cases ?
To sum up:
- @Satisfy is called from program code, and works
- @Verify should be called in testcase, to validate the code annotated by @Satisfy but it doesnt work.
Satisfy:
package com.example.demo;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) // The annotation will be available at runtime
@Target(ElementType.METHOD) // This annotation can only be applied to methods
public @interface Satisfy
{
String requirementId() default "No requirementId provided";
}
Verify:
package com.example.demo;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) // The annotation will be available at runtime
@Target(ElementType.METHOD) // This annotation can only be applied to methods
public @interface Verify
{
String requirementId() default "No requirementId provided";
}
SatisfyAspect:
package com.example.demo;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.lang.reflect.Method;
@Aspect
@Component
public class SatisfyAspect
{
@Around("@annotation(com.example.demo.Satisfy)")
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable
{
System.out.println("ENTER SatisfyAspect");
Object proceed = joinPoint.proceed();
return proceed;
}
}
VerifyAspect:
package com.example.demo;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.lang.reflect.Method;
@Aspect
@Component
public class VerifyAspect
{
@Around("@annotation(com.example.demo.Verify)")
public Object verify(ProceedingJoinPoint joinPoint) throws Throwable
{
System.out.println("ENTER VerifyAspect");
Object proceed = joinPoint.proceed();
return proceed;
}
}
Addition class with add requirement: The requirementId is composed of gilab projectid - issue iid
package com.example.demo;
import org.springframework.stereotype.Component;
@Component
public class Addition
{
@Satisfy(requirementId="12345678-1")
int add(int a, int b)
{
return a + b;
}
}
TestApplication:
package com.example.demo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class DemoApplicationTests
{
@Autowired
private Addition addition;
@Test
void contextLoads()
{
}
@Test
@Verify(requirementId="12345678-1")
void testAdd()
{
assert(addition.add(1, 2) == 3);
}
}