2014-10-17 4 views
2

jUnit 및 Mockito로 구현을 테스트하려고하는데 문제가 있습니다. 다음은 "비즈니스 로직"Mockito 인터페이스와 조롱 getter/setter 메서드

public class ValueFinder { 

    public KeyValueInterface findValueForKey(KeyValueInterface keyValue){ 
     keyValue.setValue("foo"); 
     return keyValue; 
    } 

} 

JUnit 테스트 클래스

으로 문제를

public interface KeyValueInterface { 

    public abstract String getKey(); 

    public abstract void setKey(String key); 

    public abstract String getValue(); 

    public abstract void setValue(String value); 

} 

클래스 KeyValueImpl

public class KeyValueImpl implements KeyValueInterface { 

    private String key; 
    private String value; 

    @Override 
    public String getKey() { 
     return key; 
    } 

    @Override 
    public void setKey(String key) { 
     this.key = key; 
    } 

    @Override 
    public String getValue() { 
     return value; 
    } 

    @Override 
    public void setValue(String value) { 
     this.value = value; 
    } 

} 

클래스

인터페이스 KeyValueInterface을 설명하는 매우 간단한 예입니다

import static org.junit.Assert.*; 

import org.junit.Test; 
import org.mockito.Mockito; 

public class ValueFinderTest { 

    @Test 
    public void testNotMocked() { 
     KeyValueInterface keyValue = new KeyValueImpl(); 
     keyValue = (new ValueFinder()).findValueForKey(keyValue); 
     assertEquals("foo", keyValue.getValue()); // works fine 
    } 

    @Test 
    public void testMocked1() { 
     KeyValueInterface keyValue = Mockito.mock(KeyValueInterface.class); 
     keyValue = (new ValueFinder()).findValueForKey(keyValue); 
     assertEquals("foo", keyValue.getValue()); // java.lang.AssertionError: 
                // expected:<foo> but 
                // was:<null> 

    } 

    @Test 
    public void testMocked2() { 
     KeyValueInterface keyValue = Mockito.mock(KeyValueInterface.class); 
     keyValue = (new ValueFinder()).findValueForKey(keyValue); 
     Mockito.when(keyValue.getValue()).thenCallRealMethod(); 
     Mockito.doCallRealMethod().when(keyValue).setValue(Mockito.any(String.class)); 
     assertEquals("foo", keyValue.getValue()); // org.mockito.exceptions.base.MockitoException: 
                // Cannot call real method 
                // on java interface. 
                // Interface does not have 
                // any implementation! 
                // Calling real methods is 
                // only possible when 
                // mocking concrete classes. 

    } 

} 

My probelm은 필자가 통제 할 수없는 기술적 인 이유로 KeyValue를 조롱해야한다는 것입니다. 따라서 메서드 testNotMocked()로 갈 수는 없습니다. 또한 내 제어 할 수없는 기술적 이유 때문에 인터페이스를 조롱해야합니다 (클래스가 아님).

이것을 달성 할 방법이 있습니까?

고마워요.

답변

2

, 당신은 다음과 같은 작성합니다

/** 
* Sets "foo" as the value of the given keyValue, and returns it 
*/ 

을 당신은 안 getValue()이 이전에 설정된 값을 리턴한다고 가정하십시오. 이것은 모의가 당신이하는 일 외에 다른 일을하지 않기 때문에 모의는 그렇게하지 않을 것입니다. 인터페이스의 구현에 대해 아무 것도 가정하지 않고 메소드 계약을 테스트하기 만하면됩니다. 당신이 주어진 클래스 또는 인터페이스의 모의 객체를 생성 것을 볼 수 있습니다 다음은 모의 방법에 대한 Mockito의 API를 확인한다면 테스트는

@Test 
public void testMocked1() { 
    KeyValueInterface keyValue = Mockito.mock(KeyValueInterface.class); 
    KeyValueInterface result = (new ValueFinder()).findValueForKey(keyValue); 

    // tests that the value has been set to "foo" 
    verify(keyValue).setValue("foo"); 

    // tests that the method returns its argument 
    assertSame(keyValue, result); 
} 
1

모의은 Impl 클래스에 대해 아무것도 모릅니다. 따라서 verifysetValue으로 사용하거나 스파이를 사용하여 전화 방법을 사용하십시오. 당신은 당신도 인터페이스의 방법 중 하나가 무엇을하는지 모르고, 테스트하는 방법의 자바 독을 작성한다면

0

을해야합니다.

public static <T> T mock(java.lang.Class<T> classToMock) 

따라서 첫 번째 방법 인 testMocked1()의 오류가 유효합니다. 실제로 거기에서하는 일은 간접적으로 인터페이스에 대한 impl을 조롱하는 것입니다. 그래서 당신이 할 때 모든 메서드를 조롱 얻을 getValue() String 문자열을 반환하므로 NULL NULL 반환됩니다.) (제 2 방법 testMocked2 비슷하게 testMocked1()

assertEquals("foo", keyValue.getValue()); 

를 키 값을 직접

ReflectionTestUtils.setField(classObject, key,keyvalue); 

를 설정하고 방법 아래 할 아래와 같은 ReflectionUtils를 사용하여 값을 설정 reflectionutils를 사용하여 동일한 작업을 수행 Mockito의 API 메소드를 사용하십시오.

+0

감사합니다. 스프링 프레임 워크의 ReflectionTestUtils를 의미합니까? – Paul

+0

네,하지만 일반적인 아이디어는 어디서나 동일해야합니다. – vikeng21

관련 문제