[SPRING] 요청 문맥에 의존하는 메소드를 테스트하는 유닛
SPRING요청 문맥에 의존하는 메소드를 테스트하는 유닛
다음 줄이 포함 된 메서드에 대한 단위 테스트를 작성하고 있습니다.
String sessionId = RequestContextHolder.currentRequestAttributes().getSessionId();
다음 오류가 발생합니다.
그 이유는 아주 명백합니다. 요청 컨텍스트에서 테스트를 실행하지 않습니다.
문제는 테스트 환경의 요청 컨텍스트에 종속 된 메서드 호출을 포함하는 메서드를 테스트하려면 어떻게해야합니까?
고맙습니다.
해결법
-
==============================
1.RequestAttributes 객체를 모방하거나 스텁하여 원하는 것을 반환 한 다음 테스트를 시작하기 전에 모의 / 스텁과 함께 RequestContextHolder.setRequestAttributes (RequestAttributes)를 호출 할 수 있습니다.
RequestAttributes 객체를 모방하거나 스텁하여 원하는 것을 반환 한 다음 테스트를 시작하기 전에 모의 / 스텁과 함께 RequestContextHolder.setRequestAttributes (RequestAttributes)를 호출 할 수 있습니다.
@Mock private RequestAttributes attrs; @Before public void before() { MockitoAnnotations.initMocks(this); RequestContextHolder.setRequestAttributes(attrs); // do you when's on attrs } @Test public void testIt() { // do your test... }
-
==============================
2.스프링 테스트는 MockHttpServletRequest라는 유연한 요청 모의가있다.
스프링 테스트는 MockHttpServletRequest라는 유연한 요청 모의가있다.
MockHttpServletRequest request = new MockHttpServletRequest(); RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));
-
==============================
3.당신의 수업을 다음과 같이 가정하십시오.
당신의 수업을 다음과 같이 가정하십시오.
class ClassToTest { public void doSomething() { String sessionId = RequestContextHolder.currentRequestAttributes().getSessionId(); // Do something with sessionId } }
RequestContextHolder를 사용하는 클래스를 변경할 수없는 경우 테스트 코드에서 RequestContextHolder 클래스를 재정의 할 수 있습니다. 나. 동일한 패키지에 같은 이름의 클래스를 생성하고 실제 Spring 클래스보다 먼저로드되는지 확인하십시오.
package org.springframework.web.context.request; public class RequestContextHolder { static RequestAttributes currentRequestAttributes() { return new MyRequestAttributes(); } static class MyRequestAttributes implements RequestAttributes { public String getSessionId() { return "stub session id"; } // Stub out the other methods. } }
이제 테스트가 실행되면 RequestContextHolder 클래스를 선택하여 Spring에 우선적으로 사용하게된다 (classpath가 설정되었다고 가정 할 때). 테스트를 실행하는 좋은 방법은 아니지만 테스트 할 클래스를 변경할 수없는 경우 필요할 수 있습니다.
또는 추상화 뒤에 세션 ID 검색을 숨길 수 있습니다. 예를 들어 인터페이스 소개 :
public interface SessionIdAccessor { public String getSessionId(); }
구현 만들기 :
public class RequestContextHolderSessionIdAccessor implements SessionIdAccessor { public String getSessionId() { return RequestContextHolder.currentRequestAttributes().getSessionId(); } }
그리고 클래스에서 추상화를 사용하십시오.
class ClassToTest { SessionIdAccessor sessionIdAccessor; public ClassToTest(SessionIdAccessor sessionIdAccessor) { this.sessionIdAccessor = sessionIdAccessor; } public void doSomething() { String sessionId = sessionIdAccessor.getSessionId(); // Do something with sessionId } }
그런 다음 테스트에 더미 구현을 제공 할 수 있습니다.
public class DummySessionIdAccessor implements SessionIdAccessor { public String getSessionId() { return "dummy session id"; } }
이런 종류의 일은 추상화 뒤에있는 특정 환경 세부 정보를 숨기기위한 일반적인 최상의 방법을 강조하므로 환경이 바뀌면이를 바꿀 수 있습니다. 이는 더미 구현을 '실제'구현과 바꿔서 테스트가 덜 부서지기 쉽도록 똑같이 적용됩니다.
-
==============================
4.다음을 포함한 메소드 :
다음을 포함한 메소드 :
String sessionId = RequestContextHolder.currentRequestAttributes().getSessionId();
웹 컨트롤러 메소드 인 경우 메소드 서명을 변경하여 메소드에 별도의 paremter로 요청을 전달할 것을 권장합니다.
그런 다음 troublemaker 부분 인 String RequestContextHolder.currentRequestAttributes ()를 제거하고 HttpSession을 직접 사용할 수 있습니다.
그런 다음 테스트에서 조롱 된 Session (MockHttpSession) 객체를 사용하는 것은 매우 쉽습니다.
@RequestMapping... public ModelAndView(... HttpSession session) { String id = session.getId(); ... }
from https://stackoverflow.com/questions/9419606/unit-testing-a-method-dependent-to-the-request-context by cc-by-sa and MIT license