본문 바로가기

Web/spring

[Spring framework testing] 5. Spring TestContext Framework (2)

728x90

5.6. Context Management ~ 5.8. Testing Request- and Session-scoped Beans

https://docs.spring.io/spring-framework/docs/current/reference/html/testing.html#testcontext-ctx-management
 

Testing

The classes in this example show the use of named hierarchy levels in order to merge the configuration for specific levels in a context hierarchy. BaseTests defines two levels in the hierarchy, parent and child. ExtendedTests extends BaseTests and instruct

docs.spring.io

 

틀린 해석이나 내용이 있다면 알려주세요 🤨

 


5.6. Context Management

각 TestContext 는 담당 test instance에 대한 context management 및 캐싱지원을 제공한다

test instance는 구성된 ApplicationContext에 대한 액세스 권한을 자동으로 받지 않는다

그러나 테스트 클래스가 ApplicationContextAware interface를 구현하는 경우 ApplicationContext에 대한 참조가 test instance에제공된다

AbstractJUnit4SpringContextTests 및 AbstractTestNGSpringContextTests는 ApplicationContextAware를 구현하므로 ApplicationContext에 대한 액세스를 자동으로 제공한다

 

 

 

 

@Autowired ApplicationContext

As an alternative to implementing the ApplicationContextAware interface, you can inject the application context for your test class through the @Autowired annotation on either a field or setter method, as the following example shows:

@SpringJUnitConfig
class MyTest {

    @Autowired 
    ApplicationContext applicationContext;

    // class body...
}

@Autowired를 통한 ApplicationContext 주입

 

 

 

@SpringJUnitWebConfig 
class MyWebAppTest {

    @Autowired 
    WebApplicationContext wac;

    // class body...
}

 

 

@ContextConfiguration 클래스 수준에서 주석을 선언하여 구성을 수행하면 된다

테스트 클래스가 명시적 선언을 하지 않은 경우에도 구성된 ContextLoader가 기본 구성 클래스에서 Context load 방법을 결정한다

 In addition to context resource locations and component classes, an application context can also be configured through application context initializers.

 

 

구성방법들에 대한 내용은 링크로

 

 

5.7. Dependency Injection of Test Fixtures

DependencyInjectionTestExecutionListener(기본구성)를 사용하면 @ContextConfiguration 또는 관련 주석으로 구성한 애플리케이션 컨텍스트의 Bean에서 테스트 인스턴스의 종속성이 주입된다

어떤 주석을 선택하고 주석을 세터 메소드에 배치하는지 필드에 배치하는지에 따라 세터 주입, 필드 주입 또는 둘 모두를 사용할 수 있다

 

JUnit Jupiter를 사용하는 경우 선택적으로 생성자 주입을 사용할 수 있다(SpringExtension을 사용한 종속성 주입)

Spring의 주석 기반 주입 지원과의 일관성을 위해 필드 및 세터 주입을 위해

Spring의 @Autowired 주석 또는 JSR-330의 @Inject 주석을 사용할 수도 있다.

 

 

Unit Jupiter 이외의 테스트 프레임워크의 경우 TestContext 프레임워크는 테스트 클래스의 인스턴스화되지 않는다

생성자에 @Autowired 또는 @Inject를 사용은 테스트 클래스에 영향받지 않는다.

 

 

@Autowired는 유형별로 autowiring을 수행하는 데 사용되기 때문에 동일한 유형의 여러 bean 정의가 있는 경우 해당 특정 bean  접근 방식을 사용할 수 없다.

이때 @Qualifier와 함께 @Autowired를 사용하면 된다.

@Named와 함께 @Inject를 사용하도록 선택할 수 있다. 또는 테스트 클래스가 ApplicationContext에 액세스할 수 있는 경우 applicationContext.getBean 을 사용하면 되는데

applicationContext.getBean("titleRepository", TitleRepository.class) 이런 식으로 호출 하여 명시적 조회를 수행할 수 있다

 

Test instance 에 DI 를 적용하지않으려면 @Autowired 또는 @Inject 애노테이션을 붙이지 말아야한다

아니면 @ㅅTestExecutionListeners 에서 클래스를 명시적으로 구성 하고 리스너 목록에서 DependencyInjectionTestExecutionListener.class를 생략하면 종속성 주입을 완전히 비활성화할 수 있다

 

Consider the scenario of testing a HibernateTitleRepository class, as outlined in the Goals section. 

 

Testing

The classes in this example show the use of named hierarchy levels in order to merge the configuration for specific levels in a context hierarchy. BaseTests defines two levels in the hierarchy, parent and child. ExtendedTests extends BaseTests and instruct

docs.spring.io

 

 

 

@Autowired필드 주입(JUnit Jupiter 기반)

@ExtendWith(SpringExtension.class)
// specifies the Spring configuration to load for this test fixture
@ContextConfiguration("repository-config.xml")
class HibernateTitleRepositoryTests {

    // this instance will be dependency injected by type
    @Autowired
    HibernateTitleRepository titleRepository;

    @Test
    void findById() {
        Title title = titleRepository.findById(new Long(10));
        assertNotNull(title);
    }
}

 

 

또는 setter insert 시에 구성

@ExtendWith(SpringExtension.class)
// specifies the Spring configuration to load for this test fixture
@ContextConfiguration("repository-config.xml")
class HibernateTitleRepositoryTests {

    // this instance will be dependency injected by type
    HibernateTitleRepository titleRepository;

    @Autowired
    void setTitleRepository(HibernateTitleRepository titleRepository) {
        this.titleRepository = titleRepository;
    }

    @Test
    void findById() {
        Title title = titleRepository.findById(new Long(10));
        assertNotNull(title);
    }
}

 

 

use the same XML context file referenced by the @ContextConfiguration annotation (that is, repository-config.xml)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- this bean will be injected into the HibernateTitleRepositoryTests class -->
    <bean id="titleRepository" class="com.foo.repository.hibernate.HibernateTitleRepository">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

    <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
        <!-- configuration elided for brevity -->
    </bean>

</beans>

 

 

 

setter 메소드 중 하나에서 @Autowired 를 사용하는 기본 클래스에서 확장하려는 경우에 DataSource bean인 경우 여러 bean이 있을 수 있다

이럴때 setter method를 재정의 하고, @Qualifier 애노테이션을 붙여 특정 대상 빈만 나타낼 수 있다

    @Autowired
    @Override
    public void setDataSource(@Qualifier("myDataSource") DataSource dataSource) {
        super.setDataSource(dataSource);
    }

 

 

5.8. Testing Request- and Session-scoped Beans

 Request- and session-scoped beans 

 

Core Technologies

In the preceding scenario, using @Autowired works well and provides the desired modularity, but determining exactly where the autowired bean definitions are declared is still somewhat ambiguous. For example, as a developer looking at ServiceConfig, how do

docs.spring.io

요청 범위 및 세션 범위 bean 테스트 또한 가능하다

 

 

  • Ensure that a WebApplicationContext is loaded for your test by annotating your test class with @WebAppConfiguration.
  • Inject the mock request or session into your test instance and prepare your test fixture as appropriate.
  • Invoke your web component that you retrieved from the configured WebApplicationContext (with dependency injection).
  • Perform assertions against the mocks.

 

Request-scoped bean configuration

<beans>

    <bean id="userService" class="com.example.SimpleUserService"
            c:loginAction-ref="loginAction"/>

    <bean id="loginAction" class="com.example.LoginAction"
            c:username="#{request.getParameter('user')}"
            c:password="#{request.getParameter('pswd')}"
            scope="request">
        <aop:scoped-proxy/>
    </bean>

</beans>

userService bean은 session 범위의 userPreferences bean에 종속된다

UserPreferences bean은 http session에서 인스턴스화 되기 때문에

이를 모의 구성 해주어야 한다

 

 

@SpringJUnitWebConfig
class RequestScopedBeanTests {

    @Autowired UserService userService;
    @Autowired MockHttpServletRequest request;

    @Test
    void requestScope() {
        request.setParameter("user", "enigma");
        request.setParameter("pswd", "$pr!ng");

        LoginResults results = userService.loginUser();
        // assert results
    }
}

 

 

 

 

 

Session-scoped bean configuration

<beans>

    <bean id="userService" class="com.example.SimpleUserService"
            c:userPreferences-ref="userPreferences" />

    <bean id="userPreferences" class="com.example.UserPreferences"
            c:theme="#{session.getAttribute('theme')}"
            scope="session">
        <aop:scoped-proxy/>
    </bean>

</beans>

 SessionScopedBeanTests에서 UserService와 MockHttpSession을 테스트 인스턴스에 주입한다.

sessionScope() 테스트 메서드 내에서 제공된 MockHttpSession에서 예상 테마 속성을 설정하여 테스트 fixture를 설정한다. userService에서 processUserPreferences() 메서드가 호출되면 사용자 서비스가 현재 MockHttpSession에 대한 세션 범위의 userPreferences에 액세스할 수 있고 구성된 테마를 기반으로 결과에 대해 assertions를 수행할 수 있다.

 

@SpringJUnitWebConfig
class SessionScopedBeanTests {

    @Autowired UserService userService;
    @Autowired MockHttpSession session;

    @Test
    void sessionScope() throws Exception {
        session.setAttribute("theme", "blue");

        Results results = userService.processUserPreferences();
        // assert results
    }
}

 

728x90