2012-05-17 5 views
4

내가 mockito를 사용하여, TDD에서 새로운 클래스 (Derived)를 쓰고 있어요 나는 다음과 같은 경우가 있습니다테스트중인 유닛에서 메소드가 호출되었는지 어떻게 알 수 있습니까?

클래스베이스 :

는 파생
public abstract class Base<T>{ 
    //....... 
    protected final T baseCreate(T entity){ 
     // implementation 
    } 
} 

클래스 (이 난 클래스입니다) TDD를 사용하여 작성 :

public class Derived extends Base<MyObject> { 
    //....... 
    public MyObject create(MyObject entity){ 
     baseCreate(entity); //This is what I want the implementation to be 
    } 
} 

나는이 baseCreate 메소드를 호출 저를 강제로 테스트를 작성하기 위해 왔을 때 - 내가 그렇게하는 방법을 이해하지 못했습니다. Derivedcreate(...) 메서드가 Base 클래스의 baseCreate(...) 메서드를 호출하는지 확인하기 위해 mockito를 사용하는 방법이 있습니까?

감사합니다.

답변

5

단위 테스트는 구현이 아닌 클래스의 동작을 테스트하는 것입니다. 그래서 당신이 Base whther 자신을 염려하지 말아야 '호출 처리 여부 오히려,의 baseCreate() 명시 적으로 호출 Derivedcerate() 외부 관찰자의 관점에서 예상대로 정확하게

+0

안녕하세요 Attila, 답변 주셔서 감사합니다.하지만 TDD로 작성 중이므로 테스트가 실패 할 때만 'Derived'클래스의 구현을 작성해야합니다. 그래서, 그 경우 구현은'return null; '이 될 수 있고 테스트는 여전히 통과 할 것입니다 ... – Noam

+1

'Base.baseCreate()'가 호출 될 때 true 조건을 테스트해야합니다. 그게 아니라면 – Attila

4

아틸라는 대부분의 경우에 적합한 않습니다. 당신이 테스트하기를 원하는 것은 create가 실제로 어떻게해야 하는지를 생각하는 것입니다. 여기있는 경우는 "baseCreate가 내가 원하는 것을 수행한다는 것을 이미 알고 있으므로 다시 테스트하지 않으려 고합니다. 그냥 호출됩니다." 이 일 수 있습니다. 그렇다면 슈퍼 클래스는 실제로 공동 작업자입니다. 상속에 대한 위임을 선호하는 이유 중 하나입니다. 그럼에도 불구하고 때로는 돌아가서 디자인 결정을 변경하기가 어렵 기 때문에 가지고있는 제품을 테스트해야합니다.

"create"가 전체적으로 원하는 작업을 수행하는지 확인하는 것이 좋지만 baseCreate가 실제로 많은 공동 작업자 설정을 필요로하는 많은 작업을 수행하는 경우가있을 수 있습니다. 그러한 것은 시험하기가 어렵고 부서지기 쉽다. 이 경우 "스파이"를 사용하고 싶을 것입니다. 스파이는 "실제"객체를 래핑하고 특별히 다른 기대를하지 않는 한 실제 메소드 호출에 위임합니다. 당신이 baseCreate 공개 할 수 있다면

,이 같은 Mockito를 사용할 수 있습니다 : 당신이 baseCreate 공개 할 수없는 경우

@RunWith(MockitoJUnitRunner.class) 
// We prepare PartialMockClass for test because it's final or we need to mock private or static methods 
public class YourTestCase { 
    @Spy 
    private Derived classUnderTest = new Derived(); 

    @Test 
    public void privatePartialMockingWithPowerMock() {   
     MyObject myObject = new MyObject(); 
     when(classUnderTest.baseCreate(myObject)).thenReturn(myObject); 

     // execute your test 
     classUnderTest.create(myObject); 

     verify(classUnderTest).baseCreate(myObject); 
    } 
} 

, 당신이 PowerMock을 사용할 수 있습니다 생각합니다. 개인적인 방법을 검증 할 수는 있지만 보호 된 방법을 수행 할 수없는 이유는 없을 것이라고 생각합니다.

@RunWith(PowerMockRunner.class) 
// We prepare PartialMockClass for test because it's final or we need to mock private or static methods 
@PrepareForTest(Derived.class) 
public class YourTestCase { 
    @Test 
    public void testCreate() {   
     Derived classUnderTest = PowerMockito.spy(new Derived()); 
     MyObject myObject = new MyObject(); 

     // use PowerMockito to set up your expectation 
     PowerMockito.doReturn(myObject).when(classUnderTest, "baseCreate", myObject); 

     // execute your test 
     classUnderTest.create(myObject); 

     // Use PowerMockito.verify() to verify result 
     PowerMockito.verifyPrivate(classUnderTest).invoke("baseCreate", myObject); 
    } 
} 
+0

안녕하세요, 먼저 - 답변 주셔서 감사합니다. 네가 말한 '스파이'를 사용해 볼게. 나중에 여기에 게시하겠습니다. – Noam

+0

@Noam, 결과는 어떻습니까? – alexsmail

1

당신은 당신이 TDD를 사용하는 말 - 그래서 아마도, Derived 또는 Base 또는 둘의 필요한 행동의 몇 가지 사양이있다. 따라서이 스펙을 중심으로 몇 가지 테스트를 작성할 것이다. 이 테스트를 통해 DerivedBase까지 확장 할 필요가 없습니다. 단순히 각 클래스의 특정 동작이 필요합니다. 상속을 전혀 사용하지 않고 구현할 수있는 동작이 될 것입니다.

테스트가 통과되면 TDD의 다음 단계가 시작됩니다. 이것은 리팩토링 단계로서 클래스의 디자인 방식 개선을 찾습니다. 이 시점에서 DerivedBase으로 확장하고 create 메서드 호출을 baseCreate으로 지정합니다.멋진 점은 리팩토링을 할 때 이미 제대로 작동하는지 테스트 할 수 있다는 것입니다.

관련 문제