2014-03-28 3 views
1

저는 스프링 테스트 중 일부에서 @Autowired MockHttpServletRequest을 사용합니다. TestNG는 테스트 프레임 워크로 사용됩니다. 클래스에 하나의 테스트 메소드 만 있으면 잘 작동합니다. 그러나 여러 테스트 메소드가있는 경우 첫 번째 실행 테스트 만 내 MockHttpServletRequest를 사용합니다. 내가 예와 함께 설명 보자autowired MockHttpServletRequest가 여러 테스트가 작동하지 않습니까?

이 예 test1() 패스에서
@WebAppConfiguration 
@ContextConfiguration({"classpath:applicationContext.xml"}) 
public class FooTest extends AbstractTestNGSpringContextTests { 

    @Autowired 
    private MockHttpServletRequest servletRequest; 

    @Test 
    public void test1() { 
     assertEquals(((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest(), servletRequest); 
    } 

    @Test 
    public void test2() { 
     assertEquals(((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest(), servletRequest); 
    } 

} 

하지만 test2() 실패! 테스트 메소드를 개별적으로 실행하면 둘 다 통과합니다. 테스트를 함께 실행하면 왜 하나의 테스트가 실패합니까?

코드를 파헤려고했지만 테스트 메소드를 실행 한 후 요청 속성을 다시 설정하는 것처럼 보였습니다.하지만이를 끌 수있는 방법을 찾지 못했습니다. 내 봄 버전은 3.2.8.RELEASE입니다.

답변

4

업데이트 :이 문제는 Spring Framework 3.2.9, 4.0.4 및 4.1에서 수정되었습니다. 자세한 내용은 SPR-11626을 참조하십시오.


글쎄, 내 친구가 ... 당신은 스프링 TestContext 프레임 워크에서 버그를 발견했다.

ServletTestExecutionListener은 각 테스트 메서드 후에 요청 특성을 다시 설정하지만 DependencyInjectionTestExecutionListener은 각 테스트 메서드 (기본값) 이전에 종속성을 다시 주입하지 않기 때문에 발생합니다. 두 번째 테스트 방법이 실행될 때 servletRequest 필드는 이전 테스트 방법에 대해 생성 된 MockHttpServletRequest을 계속 참조합니다. 반면에 ServletTestExecutionListener은 각 테스트 메소드에 대해 MockHttpServletRequest이라는 새 인스턴스를 생성하고이를 요청 속성에 설정합니다. 따라서 삽입 된 요청과 RequestContextHolder에 저장된 요청은 TestNG에서 실행되는 첫 번째 테스트 방법에 대해서만 동일합니다.

나는이 코드의 저자이기 때문에 개인적으로 사과해야하지만 ... 최대한 빨리 수정 될 것입니다. 수정 상태에 대한 자세한 내용은 SPR-11626을 참조하십시오. ;)

참고 :이 버그는 TestNG 테스트에만 적용됩니다. 이건 이 아니고이 JUnit 테스트에 적용됩니다.

해결 방법으로 영향을받는 테스트 메소드에 @DirtiesContext으로 주석을 달거나 테스트 클래스에 @DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)으로 주석을 달 수 있습니다. 이렇게하면 테스트가 예상대로 성공할 수 있습니다.

@DirtiesContext을 사용하면 각 테스트 방법을 수행 한 후에 봄을 내리게됩니다 (ApplicationContext). 그러면 테스트 속도가 저하 될 수 있습니다. 그러나 Spring 3.2.8과 4.0.3에서, 이것은 유일한 비 - 사용자 정의 솔루션이다.

다음과 같이 말하면 훨씬 효율적으로 해결할 수 있습니다.

public class AlwaysReinjectDependenciesTestExecutionListener extends AbstractTestExecutionListener { 

    public void afterTestMethod(TestContext testContext) throws Exception { 
     testContext.setAttribute(DependencyInjectionTestExecutionListener.REINJECT_DEPENDENCIES_ATTRIBUTE, Boolean.TRUE); 
    } 

} 

을 그리고 다음과 같이 테스트 클래스를 주석 : 그냥 프로젝트에서이 사용자 정의 TestExecutionListener을 정의

@TestExecutionListeners(AlwaysReinjectDependenciesTestExecutionListener.class) 

을 문제를 정리해야한다는 신속하게 실행하는 테스트 스위트를 유지한다.

감사합니다,

관련 문제