[java] Mockito를 사용하여 추상 클래스 테스트



Answers

추상을 건드리지 않고 구체적인 메소드를 테스트 할 필요가 있다면 CALLS_REAL_METHODS 를 사용할 수 있습니다 ( Morten의 답변 참조). 그러나 테스트중인 구체적인 메소드가 일부 추상화를 호출하거나 구현되지 않은 인터페이스 메소드를 호출하면 작품 - Mockito는 "자바 인터페이스에서 실제 메소드를 호출 할 수 없다"고 불평 할 것입니다.

(예, 그것은 비참한 디자인이지만 Tapestry 4와 같은 일부 프레임 워크는 당신에게 그것을 강요합니다.)

해결 방법은이 방법을 바꾸는 것입니다. 일반적인 모의 동작 (즉, 모든 것이 조롱 / 스텁 됨)을 사용하고 doCallRealMethod() 를 사용하여 명시 적으로 테스트중인 구체적인 메서드를 호출합니다. 예 :

public abstract class MyClass {
    @SomeDependencyInjectionOrSomething
    public abstract MyDependency getDependency();

    public void myMethod() {
        MyDependency dep = getDependency();
        dep.doSomething();
    }
}

public class MyClassTest {
    @Test
    public void myMethodDoesSomethingWithDependency() {
        MyDependency theDependency = mock(MyDependency.class);

        MyClass myInstance = mock(MyClass.class);

        // can't do this with CALLS_REAL_METHODS
        when(myInstance.getDependency()).thenReturn(theDependency);

        doCallRealMethod().when(myInstance).myMethod();
        myInstance.myMethod();

        verify(theDependency, times(1)).doSomething();
    }
}

추가 업데이트 :

void가 아닌 메소드의 경우, 대신에 thenCallRealMethod() 를 사용해야합니다. 예 :

when(myInstance.myNonVoidMethod(someArgument)).thenCallRealMethod();

그렇지 않으면 Mockito는 "미완료 스텁이 감지되었습니다."라고 불평 할 것입니다.

Question

나는 추상적 인 수업을 시험하고 싶다. 물론, 클래스에서 상속받은 모의 객체를 수동으로 작성할있습니다 .

내 모의 수작업 대신 조롱 프레임 워크 (나는 모키토를 사용하고 있습니다)를 사용하여이 작업을 수행 할 수 있습니까? 방법?




Mocking 프레임 워크는 테스트중인 클래스의 종속성을 조롱하는 것을 용이하게하기 위해 고안되었습니다. 조롱 프레임 워크를 사용하여 클래스를 모의 할 때 대부분의 프레임 워크는 동적으로 하위 클래스를 만들고 메서드 구현을 대체 할 때 메서드를 호출하고 가짜 값을 반환하는 코드로 대체합니다.

추상 클래스를 테스트 할 때, SUT (Subject Under Test)의 비 추상적 메서드를 실행하려고합니다. 따라서 조롱 프레임 워크는 원하는 것이 아닙니다.

혼란 스러울 부분은 당신이 연상했던 질문에 대한 대답이 당신의 추상적 인 수업에서 확장 된 모의 수공예품을 만드는 것이라고 말했습니다. 나는 그런 수업을 모의이라고 부르지 않을 것이다. 모의 (mock)는 의존성을 대체하기 위해 사용되는 클래스이며, 기대치로 프로그램되어 있으며 그러한 기대치가 충족되는지 확인하기 위해 쿼리 할 수 ​​있습니다.

대신, 나는 당신의 추상 클래스의 추상적이지 않은 서브 클래스를 정의 할 것을 제안한다. 그 결과 코드가 너무 많으면 클래스를 확장하기 어렵다는 신호일 수 있습니다.

다른 대안은 SUT를 생성하기위한 추상적 인 방법으로 테스트 케이스 자체를 추상적으로 만드는 것입니다 (다시 말해 테스트 케이스는 템플릿 메소드 디자인 패턴을 사용합니다).




실제로 추상적 인 클래스를 조롱하는 것에 대해 나쁘게 느끼게하는 사실은 기본 생성자 YourAbstractClass ()가 호출되지 않고 (mock에서 super ()가 누락되지 않음) Mockito에서 모의 ​​속성 (예 : List 속성 빈 ArrayList 또는 LinkedList와 함께).

내 추상 클래스 (기본적으로 클래스 소스 코드가 생성됨)는 목록 요소에 대한 종속성 설정자 주입을 제공하지 않으며, 수동으로 추가하려고 시도한 목록 요소를 초기화하는 생성자도 제공하지 않습니다.

클래스 속성 만 기본 초기화를 사용합니다. private List dep1 = new ArrayList; 개인 목록 dep2 = 새로운 ArrayList

따라서 실제 객체 구현 (예 : 단위 테스트 클래스의 내부 클래스 정의, 추상 메소드 재정의) 및 실제 객체의 스파이 (올바른 필드 초기화 수행)를 사용하지 않고 추상 클래스를 조롱하는 방법은 없습니다.

PowerMock만이 여기에 더 도움이된다는 것이 너무 나빴습니다.




테스트에서 익명 클래스를 사용하여 추상 클래스를 확장 할 수 있습니다. 예를 들어 (Junit 4 사용) :

private AbstractClassName classToTest;

@Before
public void preTestSetup()
{
    classToTest = new AbstractClassName() { };
}

// Test the AbstractClassName methods.



Links