如何在 SpringBootTest 上使用方面

问题描述 投票:0回答:1

我创建的一个方面在直接用于测试方法时不起作用,但在添加到辅助组件时起作用。当我直接使用它时,我怎样才能让它工作。

所以在下面的代码中,testAspect 失败了,但是 testAspectHelper 成功了。

方面内的断点显示代码在失败的测试中未命中,但在通过的测试中命中。

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();
        }
    }
}

java spring spring-boot aop aspectj
1个回答
0
投票

Aspect 充当代理,仅当它所设置的函数被另一个类调用时才会触发。如果您在常规类中有一个用 @WithTennant 注释的函数,并从同一类中的另一个函数调用该函数,它也不会触发方面。除非你想直接在你的代码中使用一个实现来测试,否则我不明白你怎么能像你那样没有帮助类。

© www.soinside.com 2019 - 2024. All rights reserved.