source

Junit 테스트 클래스 전체에서 스프링 애플리케이션 컨텍스트 재사용

gigabyte 2023. 3. 25. 11:21
반응형

Junit 테스트 클래스 전체에서 스프링 애플리케이션 컨텍스트 재사용

JUnit 테스트 케이스(통합 테스트)가 다수 있으며 논리적으로 여러 테스트 클래스로 분류되어 있습니다.

테스트 클래스당 1회 Spring 어플리케이션 컨텍스트를 로드하여 http://static.springsource.org/spring/docs/current/spring-framework-reference/html/testing.html에서 설명한 바와 같이 JUnit 테스트클래스의 모든 테스트 케이스에 재사용할 수 있습니다.

단, JUnit 테스트 클래스에서는 Spring 어플리케이션 콘텍스트를 한 번만 로드할 수 있는 방법이 있는지 궁금합니다.

WWIW는 Spring 3.0.5, JUnit 4.5를 사용하고 Maven을 사용하여 프로젝트를 구축합니다.

네, 이건 완벽하게 가능합니다.당신이 해야 할 일은 같은 것을 사용하는 것이다.locations테스트 클래스의 속성:

@ContextConfiguration(locations = "classpath:test-context.xml")

Spring은 응용 프로그램콘텍스트를 캐시합니다locations같은 경우로 간주합니다.locations는 두 번째로 표시됩니다.스프링에서는 새로운 콘텍스트를 작성하는 것이 아니라 같은 콘텍스트를 사용합니다.

저는 이 기능에 대한 기사를 썼습니다: Speeding up Spring Integration tests.또, Spring 메뉴얼 「9.3.2.1 컨텍스트 관리 및 캐싱」에도 자세하게 설명되어 있습니다.

이것은 흥미로운 의미를 내포하고 있다.스프링은 JUnit이 언제 완료되었는지 알 수 없으므로 모든 컨텍스트를 영원히 캐시하고 JVM 셧다운 후크를 사용하여 닫습니다.이 동작(특히 다른 테스트클래스가 많은 경우)locations)는, 메모리 사용량의 과다나 메모리 누수등의 원인이 될 가능성이 있습니다.콘텍스트 캐싱의 또 다른 장점입니다.

3.2.2 시점의 Tomasz Nurkiewicz의 답변에 추가한다.@ContextHierarchy주석을 사용하여 연결된 개별 다중 컨텍스트 구조를 가질 수 있습니다.이는 여러 테스트클래스가 메모리 내 데이터베이스 셋업(예를 들어 datasource, Entity Manager Factory, tx manager 등)을 공유하는 경우에 도움이 됩니다.

예를 들어 다음과 같습니다.

@ContextHierarchy({
  @ContextConfiguration("/test-db-setup-context.xml"),
  @ContextConfiguration("FirstTest-context.xml")
})
@RunWith(SpringJUnit4ClassRunner.class)
public class FirstTest {
 ...
}

@ContextHierarchy({
  @ContextConfiguration("/test-db-setup-context.xml"),
  @ContextConfiguration("SecondTest-context.xml")
})
@RunWith(SpringJUnit4ClassRunner.class)
public class SecondTest {
 ...
}

이 셋업에 의해 "test-db-setup-context.xml"을 사용하는 컨텍스트는 1회만 작성되지만 그 안에 있는 콩은 개별 유닛 테스트의 컨텍스트에 삽입할 수 있습니다.

매뉴얼에 대한 자세한 내용은http://http://docs.spring.io/spring/docs/current/spring-framework-reference/html/testing.html#testcontext-ctx-management 를 참조해 주세요.

한 가지 주목할 점은 @SpringBoot을 사용할 경우Tests but 다시 말하지만 Spring은 모든 테스트에 응용 프로그램콘텍스트를 재사용할 방법이 없습니다.

해결 방법 및 해결 방법.

@SpringBootTests(webEnvironment = WebEnvironment.RANDOM_PORT, classes = Application.class)
public abstract class AbstractIT {

   @MockBean
   private ProductService productService;

   @MockBean
   private InvoiceService invoiceService;

}

그러면 테스트 클래스는 다음과 같이 볼 수 있습니다.

public class ProductControllerIT extends AbstractIT {
   // please don't use @MockBean here
   @Test
   public void searchProduct_ShouldSuccess() {
   }

}

public class InvoiceControllerIT extends AbstractIT {
   // please don't use @MockBean here
   @Test
   public void searchInvoice_ShouldSuccess() {
   }

}

기본적으로 다른 테스트클래스에서 동일한 애플리케이션콘텍스트 설정을 사용하고 있는 경우, 이 설정을 실시할 수 있는 것은 스프링으로 충분합니다.예를 들어 다음과 같은 2개의 클래스A와 B가 있다고 합니다.

@ActiveProfiles("h2")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class A {

    @MockBean
    private C c;
    //Autowired fields, test cases etc...
}

@ActiveProfiles("h2")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class B {

    @MockBean
    private D d;
    //Autowired fields, test cases etc...
}

이 예에서는 클래스 A는 콩 C를, 클래스 B는 콩 D를 모킹합니다.따라서 스프링은 이러한 설정을 2개의 다른 설정으로 간주하기 때문에 어플리케이션콘텍스트는 클래스A용으로 1회, 클래스B용으로 1회 로드됩니다.

이 두 클래스 간에 애플리케이션 컨텍스트를 스프링이 공유하도록 하려면 다음과 같이 해야 합니다.

@ActiveProfiles("h2")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class A {

    @MockBean
    private C c;

    @MockBean
    private D d;
    //Autowired fields, test cases etc...
}

@ActiveProfiles("h2")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class B {

    @MockBean
    private C c;

    @MockBean
    private D d;
    //Autowired fields, test cases etc...
}

이와 같이 클래스를 배선하면 테스트 스위트에서 먼저 실행되는 클래스에 따라 클래스 A 또는 클래스B 중 하나에 대해 응용 프로그램콘텍스트가 1회만 로딩됩니다.이 클래스는 여러 테스트클래스에 걸쳐 복제할 수 있지만 테스트클래스를 다르게 커스터마이즈할 수 없습니다.테스트 클래스가 다른 클래스와 다른 커스터마이즈(스프링의 관점에서)는, 봄까지 다른 애플리케이션 콘텍스트를 작성하게 됩니다.

다음과 같은 구성 클래스를 만듭니다.

@ActiveProfiles("local")
@RunWith(SpringJUnit4ClassRunner.class )
@SpringBootTest(classes ={add your spring beans configuration classess})
@TestPropertySource(properties = {"spring.config.location=classpath:application"})
@ContextConfiguration(initializers = ConfigFileApplicationContextInitializer.class)
public class RunConfigration {

    private ClassLoader classloader = Thread.currentThread().getContextClassLoader();

    private static final Logger LOG = LoggerFactory.getLogger(S2BXISINServiceTest.class);


    //auto wire all the beans you wanted to use in your test classes
    @Autowired
    public XYZ xyz;
    @Autowired
    public ABC abc;


    }



Create your test suite like below



@RunWith(Suite.class)
@Suite.SuiteClasses({Test1.class,test2.class})
public class TestSuite extends RunConfigration {

    private ClassLoader classloader = Thread.currentThread().getContextClassLoader();

    private static final Logger LOG = LoggerFactory.getLogger(TestSuite.class);


}

다음과 같은 테스트 클래스를 만듭니다.

public class Test1 extends RunConfigration {


  @Test
    public void test1()
    {
    you can use autowired beans of RunConfigration classes here 
    }

}


public class Test2a extends RunConfigration {

     @Test
    public void test2()
    {
    you can use autowired beans of RunConfigration classes here 
    }


}

언급URL : https://stackoverflow.com/questions/8501975/reuse-spring-application-context-across-junit-test-classes

반응형