Spring,Spring Boot,TestNG 테스트 가이드-테스트@Configuration

Github 주소
Spring 이 자바 Config 체 제 를 도입 한 후에 우 리 는@Configuration 을 사용 하여 Bean 을 등록 하고 Spring Boot 는 이 체 제 를 더욱 광범 위 하 게 사용 할 것 이다.그 가 제공 하 는 대량의 Auto Configuration 은 설정 작업 을 크게 간소화 했다.그렇다면 문제 가 생 겼 습 니 다.@Configuration 과 Auto Configuration 이 예상 한 대로 실 행 될 수 있 도록 어떻게 확보 하 시 겠 습 니까?Bean 을 정확하게 등록 하 셨 습 니까?이 장 에 서 는@Configuration 과 Auto Configuration 을 테스트 하 는 방법 을 예 로 들 수 있 습 니 다.(Auto Configuration 도@Configuration 이기 때문에 테스트 방법 은 같 습 니 다.)
예 1:테스트@Configuration
먼저 간단 한@Configuration 을 쓰 겠 습 니 다.
@Configuration
public class FooConfiguration {

  @Bean
  public Foo foo() {
    return new Foo();
  }

}

그리고 FooConfiguration 이 Bean 을 정확하게 등록 할 수 있 는 지 확인 합 니 다.
public class FooConfigurationTest {

  private AnnotationConfigApplicationContext context;

  @BeforeMethod
  public void init() {
    context = new AnnotationConfigApplicationContext();
  }

  @AfterMethod(alwaysRun = true)
  public void reset() {
    context.close();
  }

  @Test
  public void testFooCreation() {
    context.register(FooConfiguration.class);
    context.refresh();
    assertNotNull(context.getBean(Foo.class));
  }

}

위 코드 에서 Context 에 대한 코드 를 주의 하 십시오:
  • 우선,우 리 는 Context
  • 를 구성한다.
  • 그리고 FooConfiguration
  • 을 등록 합 니 다.
  • 그리고 Context
  • 를 새로 고침 합 니 다.
  • 마지막 으로 테스트 방법 끝 에 close Context
  • Spring Boot 에서@Configuration 테스트 에 관 한 소스 코드 를 보면 위의 코드 와 약간 다른 것 을 발견 할 수 있 습 니 다.
    public class DataSourceAutoConfigurationTests {
    
        private final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    
        @Before
        public void init() {
            EmbeddedDatabaseConnection.override = null;
            EnvironmentTestUtils.addEnvironment(this.context,
                    "spring.datasource.initialize:false",
                    "spring.datasource.url:jdbc:hsqldb:mem:testdb-" + new Random().nextInt());
        }
    
        @After
        public void restore() {
            EmbeddedDatabaseConnection.override = null;
            this.context.close();
        }

    Spring 과 Spring Boot 는 모두 JUnit 으로 테스트 를 하 는데 JUnit 의 특성 상 테스트 방법 을 실행 할 때마다 new 테스트 클래스 인 스 턴 스 가 있 고 TestNG 는 같은 테스트 클래스 인 스 턴 스 를 공유 하고 있 기 때 문 입 니 다.
    예 2:테스트@Conditional
    Spring Framework 는@Configuration 을 조건 부 로 제어 할 수 있 는 메커니즘 을 제공 합 니 다.즉,특정한 조건 을 만족 시 킬 때 만@Configuration 을 가 져 올 수 있 습 니 다.이것 이 바로@conditional 입 니 다.
    다음은@Conditional 에 대해 테스트 를 해 보 겠 습 니 다.먼저 Condition FooConfiguration 을 사용자 정의 합 니 다.
    @Configuration
    public class FooConfiguration {
    
      @Bean
      @Conditional(FooCondition.class)
      public Foo foo() {
        return new Foo();
      }
    
      public static class FooCondition implements Condition {
    
        @Override
        public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
          if (context.getEnvironment() != null) {
            Boolean property = context.getEnvironment().getProperty("foo.create", Boolean.class);
            return Boolean.TRUE.equals(property);
          }
          return false;
        }
    
      }
    }

    이 Condition 은 Environment 에 있 는 지foo.create=true를 판단 한다.
    만약 에 우리 가 이 Condition 을 테스트 하려 면 Environment 에 관련 property 를 추가 해 야 합 니 다.여기 서 우 리 는 세 가지 상황 을 테스트 했 습 니 다.
  • 설정 되 지 않 음foo.create=true
  • 설정foo.create=true
  • 설정foo.create=false
  • FooConfigurationTest:
    public class FooConfigurationTest {
    
      private AnnotationConfigApplicationContext context;
    
      @BeforeMethod
      public void init() {
        context = new AnnotationConfigApplicationContext();
      }
    
      @AfterMethod(alwaysRun = true)
      public void reset() {
        context.close();
      }
    
      @Test(expectedExceptions = NoSuchBeanDefinitionException.class)
      public void testFooCreatePropertyNull() {
        context.register(FooConfiguration.class);
        context.refresh();
        context.getBean(Foo.class);
      }
    
      @Test
      public void testFooCreatePropertyTrue() {
        context.getEnvironment().getPropertySources().addLast(
            new MapPropertySource("test", Collections.singletonMap("foo.create", "true"))
        );
        context.register(FooConfiguration.class);
        context.refresh();
        assertNotNull(context.getBean(Foo.class));
      }
    
      @Test(expectedExceptions = NoSuchBeanDefinitionException.class)
      public void testFooCreatePropertyFalse() {
        context.getEnvironment().getPropertySources().addLast(
            new MapPropertySource("test", Collections.singletonMap("foo.create", "false"))
        );
        context.register(FooConfiguration.class);
        context.refresh();
        assertNotNull(context.getBean(Foo.class));
      }
    
    }

    다음 방법 으로 Environment 에 property 를 추가 하 는 것 을 주의 하 십시오.
    context.getEnvironment().getPropertySources().addLast(
      new MapPropertySource("test", Collections.singletonMap("foo.create", "true"))
    );

    따라서@Condition al 과 이에 대응 하 는 Condition 에 대한 테스트 는 근본적으로 다른 조건 을 주 고 그 행위 가 정확 한 지 판단 하 는 것 입 니 다.이 예 에서 우리 의 Condition 은 비교적 간단 합 니 다.다만 특정한 property 가 존재 하 는 지 판단 할 뿐 복잡 한 Condition 이 있다 면 테스트 방향 도 마찬가지 입 니 다.
    예 3:테스트@ConditionalOnProperty
    Spring framework 는@conditional 만 제공 합 니 다.Spring boot 는 이 메커니즘 을 확장 하여 더욱 풍부 한@conditional On*을 제공 합 니 다.여 기 는@conditional OnProperty 로 예 를 들 어 설명 합 니 다.
    FooConfiguration 먼저 보기:
    @Configuration
    public class FooConfiguration {
    
      @Bean
      @ConditionalOnProperty(prefix = "foo", name = "create", havingValue = "true")
      public Foo foo() {
        return new Foo();
      }
    
    }

    FooConfigurationTest:
    public class FooConfigurationTest {
    
      private AnnotationConfigApplicationContext context;
    
      @BeforeMethod
      public void init() {
        context = new AnnotationConfigApplicationContext();
      }
    
      @AfterMethod(alwaysRun = true)
      public void reset() {
        context.close();
      }
    
      @Test(expectedExceptions = NoSuchBeanDefinitionException.class)
      public void testFooCreatePropertyNull() {
        context.register(FooConfiguration.class);
        context.refresh();
        context.getBean(Foo.class);
      }
    
      @Test
      public void testFooCreatePropertyTrue() {
        EnvironmentTestUtils.addEnvironment(context, "foo.create=true");
        context.register(FooConfiguration.class);
        context.refresh();
        assertNotNull(context.getBean(Foo.class));
      }
    
      @Test(expectedExceptions = NoSuchBeanDefinitionException.class)
      public void testFooCreatePropertyFalse() {
        EnvironmentTestUtils.addEnvironment(context, "foo.create=false");
        context.register(FooConfiguration.class);
        context.refresh();
        assertNotNull(context.getBean(Foo.class));
      }
    
    }

    이 테스트 코드 와 예 2 의 논리 적 차 이 는 많 지 않 습 니 다.예 2 에 서 는 우리 가 쓴 Condition 을 사 용 했 을 뿐 입 니 다.여 기 는 Spring Boot 가 제공 하 는@conditional OnProperty 를 사 용 했 습 니 다.
    또한 Spring Boot 가 제공 하 는 Environment TestUtils 를 이용 하여 Environment 에 property 를 추가 하 는 작업 을 간소화 했다.
    EnvironmentTestUtils.addEnvironment(context, "foo.create=false");

    예 4:구성 속성 테스트
    Spring Boot 는 형식 이 안전 한 Configuration Properties 도 제공 합 니 다.예 를 들 어 어떻게 테스트 하 는 지 보 여 줍 니 다.
    BarConfiguration:
    @Configuration
    @EnableConfigurationProperties(BarConfiguration.BarProperties.class)
    public class BarConfiguration {
    
      @Autowired
      private BarProperties barProperties;
    
      @Bean
      public Bar bar() {
        return new Bar(barProperties.getName());
      }
    
      @ConfigurationProperties("bar")
      public static class BarProperties {
    
        private String name;
    
        public String getName() {
          return name;
        }
    
        public void setName(String name) {
          this.name = name;
        }
      }
    
    }

    BarConfigurationTest:
    public class BarConfigurationTest {
    
      private AnnotationConfigApplicationContext context;
    
      @BeforeMethod
      public void init() {
        context = new AnnotationConfigApplicationContext();
      }
    
      @AfterMethod(alwaysRun = true)
      public void reset() {
        context.close();
      }
    
      @Test
      public void testBarCreation() {
        EnvironmentTestUtils.addEnvironment(context, "bar.name=test");
        context.register(BarConfiguration.class, PropertyPlaceholderAutoConfiguration.class);
        context.refresh();
        assertEquals(context.getBean(Bar.class).getName(), "test");
      }
    
    }

    Configuration Properties 체 제 를 사 용 했 기 때문에 Property Placeholder AutoConfiguration 을 등록 해 야 합 니 다.그렇지 않 으 면 BarConfiguration 에 BarProperties 를 주입 할 수 없습니다.
    참고 문서
  • Conditionally include @Configuration classes or @Bean methods
  • Condition annotations
  • Type-safe Configuration Properties
  • Spring Framework Testing
  • Spring Boot Testing
  • 좋은 웹페이지 즐겨찾기