programing

SpringBootTest로 측면을 테스트하는 방법은 무엇입니까?

stoneblock 2023. 6. 23. 21:43

SpringBootTest로 측면을 테스트하는 방법은 무엇입니까?

Spring Boot 2.1.6을 사용하여 봄에 간단한 측면을 만들었습니다.풀어주다.기본적으로 메서드에 소요된 총 시간을 기록합니다.

@Aspect
@Component
public class TimeLoggerAspect {

  private static final Logger log = LoggerFactory.getLogger(TimeLoggerAspect.class);

  @Around("@annotation(demo.TimeLogger)")
  public Object methodTimeLogger(ProceedingJoinPoint joinPoint) 
          throws Throwable {
    long startTime = System.currentTimeMillis();

    Object proceed = joinPoint.proceed();

    long totalTime = System.currentTimeMillis() - startTime;
    log.info("Method " + joinPoint.getSignature() + ": " + totalTime + "ms");

    return proceed;
  }
}

양상은 에 의해 촉발됩니다.TimeLogger주석

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface TimeLogger {
}

그리고 이와 같은 구성 요소에 사용됩니다.

@Component
public class DemoComponent {
  @TimeLogger
  public void sayHello() {
    System.out.println("hello");
  }
}

스프링 부트 데모 애플리케이션이 실행됩니다.sayHello경유로run의 방법CommandLineRunner인터페이스

@SpringBootApplication
public class DemoApplication implements CommandLineRunner {

  @Autowired
  private DemoComponent demoComponent;

  public static void main(String[] args) {
    SpringApplication.run(DemoApplication.class, args);
  }

  @Override
  public void run(String... args) throws Exception {
    demoComponent.sayHello();
  }
}

완전성을 위해 수정 사항을 다음에 추가합니다.build.gradleaop, 스프링 테스트 및 주피터(junit)를 위한 라이브러리 추가.

    compile("org.springframework.boot:spring-boot-starter-aop")

    testCompile("org.springframework.boot:spring-boot-starter-test")
    testCompile("org.junit.jupiter:junit-jupiter-api")
    testRuntime("org.junit.jupiter:junit-jupiter-engine")

응용 프로그램을 실행하면 출력됩니다(가독성을 위해 잘림).

hello
... TimeLoggerAspect : Method void demo.DemoComponent.sayHello(): 4ms

지금까지, 좋아요.이제 다음을 기반으로 테스트를 만듭니다.@SpringBootTest주석과 주피터.

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;

@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = {DemoComponent.class, TimeLoggerAspect.class})
public class DemoComponentFailTest {

  @Autowired
  private DemoComponent demoComponent;

  @Test
  public void shouldLogMethodTiming() {
      demoComponent.sayHello();
  }
}

그리고 여기서 나는 출력을 얻습니다.

hello

에서 출력 없음TimeLoggerAspect그것이 촉발되지 않은 것처럼 보이기 때문입니다.

테스트에서 측면을 트리거할 무언가가 누락되었습니까?아니면 스프링 부츠의 측면을 테스트하는 다른 방법이 있습니까?

저도 비슷한 문제가 있었어요.나의 관점은 컨트롤러 메소드를 듣는 것입니다.활성화하려면 다음 항목을 가져옵니다.AnnotationAwareAspectJAutoProxyCreator속임수를 쓴 것:

@RunWith(SpringRunner.class)
@Import(AnnotationAwareAspectJAutoProxyCreator.class) // activate aspect
@WebMvcTest(MyController.class)
public class MyControllerTest {

    ...

}

@EnableAspect를 입력해야 합니다.@Aspect로 빈을 선언하는 @Configuration 파일을 사용하는 JAutoProxy.

@Aspect
@Configuration
@EnableAspectJAutoProxy
public class TimeLoggerAspect {

  private static final Logger log = LoggerFactory.getLogger(TimeLoggerAspect.class);

  @Around("@annotation(demo.TimeLogger)")
  public Object methodTimeLogger(ProceedingJoinPoint joinPoint) 
          throws Throwable {
    long startTime = System.currentTimeMillis();

    Object proceed = joinPoint.proceed();

    long totalTime = System.currentTimeMillis() - startTime;
    log.info("Method " + joinPoint.getSignature() + ": " + totalTime + "ms");

    return proceed;
  }
}

그 정도면 될 것 같습니다.

시작해야 합니다.@SpringBootApplication그러나 운영 환경에서 앱을 시작하는 데 사용할 필요는 없습니다.이 테스트에만 특수한 테스트일 수 있으며 src가 아닌 테스트 소스 루트에 있을 수 있습니다.

@SpringBootApplication
@ComponentScan(basePackageClasses = {DemoComponent.class, TimeLoggerAspect.class})
public class SpringBootTestMain {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootTestMain.class, args);
    }

}

그러면 테스트에서 이 클래스만 나열하면 됩니다.

@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = SpringBootTestMain.class)
public class DemoComponentFailTest {

효과가 있는 것으로 보이는 또 다른 솔루션은 다음과 같은 기능을 추가하는 것입니다.classes@SpringBootTest왜 그런지는 잘 모르겠지만요.

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;

@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = { DemoComponent.class, 
                            TimeLoggerAspect.class,
                            AnnotationAwareAspectJAutoProxyCreator.class })
public class DemoComponentFailTest {

  @Autowired
  private DemoComponent demoComponent;

  @Test
  public void shouldLogMethodTiming() {
      demoComponent.sayHello();
  }
}

측면을 테스트해야 할 때 아래의 방법을 사용했습니다.

@SpringBootTest
@ContextConfiguration(classes = {MyAspectImpl.class, MyAspectTest.TestConfiguration.class})
@EnableAspectJAutoProxy
public class MyAspectTest {

  @org.springframework.boot.test.context.TestConfiguration
static class TestConfiguration {
    @Bean
    public MyAspectTestClass myAspectTestClass() {
      return new MyAspectTestClass();
    }
  }

  @Autowired
  private MyAspectTestClass target;

  @Test
  public void testCorrectlySetsPoolNameUsingMethodParameter() {
    target.testMethod();
  }

  @NoArgsConstructor
  private static class MyAspectTestClass {
    @MyAspect
    public void testMethod() {
     //Add some logic here
    }
  }
}

@Import (AnnotationAwareAspectJAutoProxyCreator.class)이것만으로는 저에게 효과가 없었습니다.

ContextConfiguration에 aspect 클래스와 컨트롤러 클래스를 포함해야 했습니다.그런 다음 테스트 클래스에서 오토와이어를 사용합니다.

@ContextConfiguration (classes = {MyController.class, MyAspect.class})

@Autowired
MyController myController;

@Autowired
MyAspect myAspect;

여기에 두고 갑니다.언젠가 누군가에게 도움이 될 거라고 생각했어요.

언급URL : https://stackoverflow.com/questions/56763066/how-to-test-an-aspect-with-springboottest