Whiteship's Note


내부에서 new 로 객체를 생성하는 코드 테스트 하기

모하니?/Coding : 2009.05.13 23:53


어렵죠? 어떻게 해야될까요? 제가 오늘 맞딱드린 상황은 생성자 내부에서 필요한 필드를 세팅하는데 new 를 사용해서 객체를 생성하더군요. 그런데 그 필드들이 굉장히 중요한 역할을 해주고 있었습니다. 하지만 너무 복잡해서 그 녀석들 그대로 테스트를 하면 테스트 하는 범위도 너무 넓고 이미 다른 곳에서 여러번 테스트 해 본 것들이라 테스트에 오히려 방해가 되는 수준까지 이르렀습니다.

    public WebTestRunner(Class<?> klass) throws InitializationError {
        super(klass);
        WebTestConfiguration wtc = klass.getAnnotation(WebTestConfiguration.class);
        if(wtc == null)
            throw new IllegalStateException();

        dataManager = createDataManager((String)getValue(wtc, "testDataLocation"));
        warManager = createWarManager((String)getValue(wtc, "appName"));
    }

대충 이렀습니다. 저 두 녀석을 mockup 하고 싶은데, 저 녀석들을 생성하는데 필요한 또 다른 설정까지 있습니다. 어떻게 해야 될까요?

결과물은 자꾸 늦게 나오는 것 같고, 시간은 마구 달려가고, 정신은 점점 혼미해지고, 어깨는 누가 짓누르는 것 같은 고통 속에서 생각난건, 테스트 하는 대상의 스텁을 만들고 스텁으로 테스트하고 싶은 부분을 테스트하면서 원본에 테스트 결과를 반영하는 것이었습니다. 그리 아름다운 방법은 아닌 것 같지만, 유용하게 써먹었습니다.

이런 스텁 구현체를 만들었죠.

    public WebTestRunnerStub(Class<?> klass) throws InitializationError {
        super(klass);
        // WebTestConfiguration wtc =
        // klass.getAnnotation(WebTestConfiguration.class);
        // if(wtc == null)
        // throw new IllegalStateException();
        //
        // dataManager = createDataManager((String)getValue(wtc,
        // "testDataLocation"));
        // warManager = createWarManager((String)getValue(wtc, "appName"));
    }

src-springsprout-WebTestRunner (원본 테스트 대상)
test-springsprout-WebTestRunnerStub (원본 테스트 대상의 스텁 구현체)
                         -WebTestRunnerTest (WebTestRunnerStub에 대한 테스트)

이 상태에서 테스트 코드를 작성합니다,

    WebTestRunnerStub runner;
    WarManager mockWarManager;
    DataManager mockDataManager;

    @Before
    public void setUp() throws InitializationError{
        runner = new WebTestRunnerStub(this.getClass());
        mockWarManager = mock(WarManager.class);
        mockDataManager = mock(DataManager.class);
        runner.setWarManager(mockWarManager);
        runner.setDataManager(mockDataManager);
    }

이런식으로 mocking을 할 수 있습니다. 이 뒤에는 뭐~ 걍 하고 싶을대로 하면 되는거죠.

이렇게 해두면, 일단 네비게이션은 그다지 불편하지 않습니다.
- 테스트 코드에서 스텁으로의 이동은 Ctrl+클릭을 이용하면 되고,
- 테스트 코드에서 원본 대상으로의 이동은 Ctrl+J(MoreUnit 플러그인 설치 해야함)를 사용하면 됩니다.

테스트용 코드를 마구 심어놓을 수 있습니다.
- 스텁을 어떻게 구현해서 지지고 볶던 제 맘이고, 실제 코드에 아무런 영향도 주지 않습니다.
- 따라서 저처럼 Sysout을 좋아하시는 분들은 맘대로 원한는 곳에 Sysout을 심어 두어도 관계 없습니다.

하지만 다소 큰 단점이 있습니다. 눈으로 동기화를 해줘야 합니다.
- 원본과 스텁이 똑같을 필요는 없지만, 테스트 하는 부분에 있어서 중요 로직은 동일해야겠죠.

젤 좋은 방법은 IoC가 가능한 구조로 바꾸는 건데 JUnit의 BlockJUnit4ClassRunner 클래스를 상속하여 만든 클래스라서...  IoC 구조로 만들어 사용하기가 좀 애매하네요..@_@

좋은 방법은 아닌거 같지만 나름 편리한 방법이오니, 테스트하기 불편한 클래스의 테스트가 급하신 분들은 이용해 보세요. ㅋㅋ
top

  1. Favicon of https://helols.tistory.com BlogIcon is윤군 2009.05.14 09:50 신고 PERM. MOD/DEL REPLY

    의외로 간단하게 풀었네요 ;;ㅋㅋ

    Favicon of http://whiteship.me BlogIcon 기선 2009.05.14 12:13 PERM MOD/DEL

    ㅇㅇ난 복잡한건 질색이라..@_@

Write a comment.