복붙노트

[SPRING] 요청 문맥에 의존하는 메소드를 테스트하는 유닛

SPRING

요청 문맥에 의존하는 메소드를 테스트하는 유닛

다음 줄이 포함 된 메서드에 대한 단위 테스트를 작성하고 있습니다.

String sessionId = RequestContextHolder.currentRequestAttributes().getSessionId();

다음 오류가 발생합니다.

그 이유는 아주 명백합니다. 요청 컨텍스트에서 테스트를 실행하지 않습니다.

문제는 테스트 환경의 요청 컨텍스트에 종속 된 메서드 호출을 포함하는 메서드를 테스트하려면 어떻게해야합니까?

고맙습니다.

해결법

  1. ==============================

    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. ==============================

    2.스프링 테스트는 MockHttpServletRequest라는 유연한 요청 모의가있다.

    스프링 테스트는 MockHttpServletRequest라는 유연한 요청 모의가있다.

    MockHttpServletRequest request = new MockHttpServletRequest();
    RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));
    
  3. ==============================

    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. ==============================

    4.다음을 포함한 메소드 :

    다음을 포함한 메소드 :

    String sessionId = RequestContextHolder.currentRequestAttributes().getSessionId();
    

    웹 컨트롤러 메소드 인 경우 메소드 서명을 변경하여 메소드에 별도의 paremter로 요청을 전달할 것을 권장합니다.

    그런 다음 troublemaker 부분 인 String RequestContextHolder.currentRequestAttributes ()를 제거하고 HttpSession을 직접 사용할 수 있습니다.

    그런 다음 테스트에서 조롱 된 Session (MockHttpSession) 객체를 사용하는 것은 매우 쉽습니다.

    @RequestMapping...
    public ModelAndView(... HttpSession session) {
        String id = session.getId();
        ...
    }
    
  5. from https://stackoverflow.com/questions/9419606/unit-testing-a-method-dependent-to-the-request-context by cc-by-sa and MIT license