I have an aspect that I have created that does not work when utilised directly on a Test method, but does work when added to a helper component. How can I get this working when I use it directly.
So in the code below testAspect fails, but testAspectHelper succeeds.
A breakpoint within the aspect shows the code isn't hit in the failing test, but is hit in the test that passes.
import org.junit.jupiter.api.Test;
import org.opennms.horizon.inventory.SpringContextTestInitializer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.actuate.observability.AutoConfigureObservability;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
@SpringBootTest
@ContextConfiguration(initializers = {SpringContextTestInitializer.class})
@AutoConfigureObservability
public class AspectTest {
@Autowired
AspectTestHelper aspectTestHelper;
@Test
@WithTenant(tenantId = "Fred")
public void testAspect() {
// Test fails
assert("Fred".equals(TenantContext.getTenantId()));
}
@Test
public void testAspectHelper() {
// Test succeeds
aspectTestHelper.setTenant();
}
}
import org.springframework.stereotype.Component;
@Component
public class AspectTestHelper {
@WithTenant(tenantId = "Alex")
public void setTenant() {
assert("Alex".equals(TenantContext.getTenantId()));
}
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface WithTenant {
String tenantId() default "";
int tenantIdArg() default -1;
String tenantIdArgInternalMethod() default "";
String tenantIdArgInternalClass() default "";
}
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
@Component
@Aspect
public class WithTenantAspect {
private static final Logger LOG = LoggerFactory.getLogger(WithTenantAspect.class);
@Autowired
private TenantLookup tenantLookup;
@Around(("@annotation(withTenant)"))
public Object getTenant(ProceedingJoinPoint joinPoint, WithTenant withTenant) throws Throwable {
String tenantId = withTenant.tenantId();
int tenantIdArg = withTenant.tenantIdArg();
String tenantIdArgInternalMethod = withTenant.tenantIdArgInternalMethod();
String tenantIdArgInternalClass = withTenant.tenantIdArgInternalClass();
if (tenantIdArg >= 0) {
Object[] args = joinPoint.getArgs();
if (args.length <= tenantIdArg) {
throw new RuntimeException("TenantIdArg position is greater than the number of arguments to the method");
}
if (tenantIdArgInternalMethod == null || tenantIdArgInternalMethod.isEmpty() || tenantIdArgInternalClass == null || tenantIdArgInternalClass.isEmpty()) {
tenantId = String.valueOf(args[tenantIdArg]);
} else {
Object tenantObj = args[tenantIdArg];
Class clazz = Class.forName(tenantIdArgInternalClass);
Method method = clazz.getMethod(tenantIdArgInternalMethod);
Object tenant = method.invoke(tenantObj);
tenantId = String.valueOf(tenant);
}
}
if (tenantId == null || tenantId.isEmpty()) {
tenantId = tenantLookup.lookupTenantId().orElseThrow();
}
try {
TenantContext.setTenantId(tenantId);
Object proceed = joinPoint.proceed();
return proceed;
} finally {
TenantContext.clear();
}
}
}