카테고리 없음

테스트 클래스 외부에서 Spring Boot / JUnit 5를 사용하여 테스트 수명주기 이벤트에 연결

기록만이살길 2021. 2. 23. 20:05
반응형

테스트 클래스 외부에서 Spring Boot / JUnit 5를 사용하여 테스트 수명주기 이벤트에 연결

1. 질문(문제점):

JUnit을 (5) 등의 기능을 가지고 있습니다 @BeforeEach, @BeforeAll, @AfterAll, @AfterEach당신이 그렇지 않으면 시험을 공유 할 것이다 명확한 상태로, 예를 들어, 테스트 생명주기 이벤트 기간 동안 코드를 실행할 수 주석.

각 테스트에 이러한 수명주기 후크를 넣는 것을 기억할 필요없이 특정 테스트 구성에 대해이 작업을 자동으로 수행하는 방법을 원합니다.

예를 들면 :

일부 스텁 데이터 소스를로드하는 Spring 테스트 구성이있는 경우 :

interface DataProvider {
    String getData(String id);
}

그리고 이것에 의존하는 클래스 :

@Component
class ClassThatDependsOnDataProvider {
    private final DataProvider dataProvider;

    @Autowired
    ClassThatDependsOnDataProvider(DataProvider dataProvider) {
        this.dataProvider = dataProvider;
    }

    public String process(String id) {
        String data = dataProvider.get(id);
        return some_processing_of(data);
    }
}

일반적으로 이것은 백엔드에 도달 할 수 있지만 테스트를 위해 메모리 내 솔루션으로 교체합니다.

@TestComponent
class InMemoryDataProvider implements DataProvider {
    private Map<String, String> data = new HashMap<>();

    public void setData(String id, String data) {
        data.put(id, data);
    }

    public String getData(String id) {
        return data.get(id);
    }

    public void clear() {
        data.clear();
    }
}

내 테스트에서 나는 이것을 사용하여 내 백엔드의 데이터를 스텁 아웃합니다.

@SpringBootTest
@Import({InMemoryDataProvider.class})
class ClassThatDependsOnDataProviderTests {
    @Autowired InMemoryDataProvider dataProvider;

    @Autowired ClassThatDependsOnDataProvider classThatDependsOnDataProvider;

    @Test
    public void should_correctly_process_data() {
        // given i have an id with a value
        dataProvider.setData("stub_id", "stub_value");

        // when i process my id
        var result = classThatDependsOnDataProvider.process("stub_id");

        // then i receive expected result
        assertThat(result).isWhatIExpect();
    }

    // more @Tests

    // DON'T WANT TO HAVE TO DO THIS IN EACH TEST CLASS
    @AfterEach
    public void tearDown() {
        dataProvider.clear();
    }
} 

tearDown()여기서 주석이 달린 메서드 를 제거하고 @AfterEach해당 동작을 테스트 구성 요소 / 테스트 가짜 또는 다른 구성 클래스로 이동하여 이러한 공급자 집합을 사용하면 집합을 쉽게 유지할 수 있기를 원합니다. 각 테스트의 수명주기를 수동으로 관리 할 필요없이 가짜 버전으로 대체 할 테스트의 수입니다.

이를 허용하는 일종의 Spring 기능, 수명주기 이벤트 또는 JUnit 5 기능이 있습니까?

간단한 예제를 용서하십시오.이 간단한 테스트에는 과잉이지만 토론을위한 참조 일뿐입니다. @MockBean모의 libs를 사용하거나 가정 하는 것은 옵션이 아닙니다.

2. 해결방안:

JUnit5 확장을 사용할 수 있습니다 : https://junit.org/junit5/docs/current/user-guide/#extensions .

예를 들어 확장은 다음과 같습니다.

public class InMemoryDataProviderExtension implements AfterEachCallback {

    /**
     * {@inheritDoc}
     */
    @Override
    public void afterEach(final ExtensionContext context) throws Exception {
        final ApplicationContext applicationContext = SpringExtension.getApplicationContext(context);

        final InMemoryDataProvider inMemoryDataProvider = applicationContext.getBean(InMemoryDataProvider.class);
        inMemoryDataProvider.clear();

    }
}

참고 :

  • SpringExtension.getApplicationContext(context); 스프링 애플리케이션 컨텍스트를 가져 오므로 컨텍스트에 정의 된 Bean을 검색 할 수 있습니다.
  • 확장은 AfterEachCallback 인터페이스를 구현하지만 다른 확장 점 (예 : BeforeEachCallback, BeforeAllCallback 등)에 대해 다른 인터페이스가 있습니다.

테스트에서 확장을 활성화하려면 :

@SpringBootTest
@ExtendWith(InMemoryDataProviderExtension.class)
public class ClassThatDependsOnDataProviderTests { ... }
65823561
반응형