Mockito 1.9.0을 사용하고 있습니다. JUnit 테스트에서 클래스의 단일 메소드에 대한 동작을 모방하고 싶습니다.
final MyClass myClassSpy = Mockito.spy(myInstance);
Mockito.when(myClassSpy.method1()).thenReturn(myResults);
문제는 두 번째 줄에서 myClassSpy.method1()
실제로 호출되어 예외가 발생한다는 것입니다. 내가 모의를 사용하는 유일한 이유는 나중에 myClassSpy.method1()
호출 될 때마다 실제 메소드가 호출되지 않고 myResults
객체가 반환되도록하기 때문입니다.
MyClass
인터페이스이며 myInstance
중요한 경우 구현입니다.
이 감시 행동을 바로 잡기 위해 어떻게해야합니까?
답변
공식 문서를 인용하겠습니다 .
실제 물체를 감시하는 데 중요한 문제가 있습니다!
때로 간첩을 찌르기 위해 when (Object)를 사용하는 것이 불가능한 경우가 있습니다. 예:
List list = new LinkedList(); List spy = spy(list); // Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty) when(spy.get(0)).thenReturn("foo"); // You have to use doReturn() for stubbing doReturn("foo").when(spy).get(0);
귀하의 경우에는 다음과 같습니다.
doReturn(resulstIWant).when(myClassSpy).method1();
답변
제 사례는 허용 된 답변과 다릅니다. 해당 패키지에 존재하지 않는 인스턴스에 대한 패키지 전용 메소드를 조롱하려고했습니다.
package common;
public class Animal {
void packageProtected();
}
package instances;
class Dog extends Animal { }
그리고 시험 수업
package common;
public abstract class AnimalTest<T extends Animal> {
@Before
setup(){
doNothing().when(getInstance()).packageProtected();
}
abstract T getInstance();
}
package instances;
class DogTest extends AnimalTest<Dog> {
Dog getInstance(){
return spy(new Dog());
}
@Test
public void myTest(){}
}
컴파일은 정확하지만 테스트 설정을 시도하면 실제 메소드가 대신 호출됩니다.
보호 된 방법 또는 공개 된 방법을 선언하면 문제가 해결되지만 깨끗한 해결책은 아닙니다.
답변
필자의 경우 Mockito 2.0을 사용 하여 실제 호출을 스텁하기 위해 모든 any()
매개 변수를 변경해야했습니다 nullable()
.
답변
Tomasz Nurkiewicz의 대답은 전체 이야기를 말하지 않는 것처럼 보입니다!
NB Mockito 버전 : 1.10.19.
나는 매우 Mockito newb이므로 다음과 같은 행동을 설명 할 수 없습니다.이 답변을 향상시킬 수있는 전문가가 있다면 자유롭게 느끼십시오.
여기서 문제가되는 방법 getContentStringValue
은 NOT final
및 NOT static
입니다.
이 줄 은 원래 메소드를 호출합니다 getContentStringValue
.
doReturn( "dummy" ).when( im ).getContentStringValue( anyInt(), isA( ScoreDoc.class ));
이 줄 은 원래 메소드를 호출 하지 않습니다getContentStringValue
.
doReturn( "dummy" ).when( im ).getContentStringValue( anyInt(), any( ScoreDoc.class ));
내가 대답 할 수없는 이유로을 사용 isA()
하면 의도 된 (?) “방법을 호출하지 않음”동작이 doReturn
실패합니다.
여기에 포함 된 메소드 시그니처를 살펴 보겠습니다 . 둘 다의 static
메소드입니다 Matchers
. 둘 다 Javadoc에 의해 리턴된다고 말하는데 null
, 그 자체로 머리를 돌리기가 약간 어렵습니다. 아마도 Class
매개 변수로 전달 된 객체는 검사되지만 결과는 계산되거나 버려지지 않습니다. 그 감안할 때 null
모든 클래스에 대한 설 수 당신이의 서명을 호출하지 않도록 조롱 방법에 대한줬으면되지 않도록 isA( ... )
하고 any( ... )
바로 돌아 null
일반적인 매개 변수보다는 * <T>
?
어쨌든:
public static <T> T isA(java.lang.Class<T> clazz)
public static <T> T any(java.lang.Class<T> clazz)
API 설명서에는 이에 대한 힌트가 없습니다. 또한 이러한 “메소드를 호출하지 마십시오”동작에 대한 요구는 “매우 드물다”고합니다. 개인적으로 저는이 기술을 항상 사용합니다 . 일반적으로 조롱에는 몇 개의 라인이 “장면을 설정”하고 그 뒤에는 여러분이 준비한 모의 문맥에서 장면을 “재생”하는 메소드가 호출됩니다. 그리고 풍경과 소품을 설정하는 동안 배우가 마지막 단계에 들어가서 그들의 마음을 연기하기 시작하는 것입니다 …
그러나 이것은 저의 급료보다 더 큽니다. 나는 지나가는 Mockito 대제사로부터 설명을 초대합니다 …
* “일반 매개 변수”가 올바른 용어입니까?
답변
스파이와 관련하여 문제를 일으킬 수있는 또 하나의 시나리오는 스프링 빈 (스프링 테스트 프레임 워크 사용) 또는 테스트 중에 객체를 근접시키는 다른 프레임 워크를 테스트 할 때 입니다.
예
@Autowired
private MonitoringDocumentsRepository repository
void test(){
repository = Mockito.spy(repository)
Mockito.doReturn(docs1, docs2)
.when(repository).findMonitoringDocuments(Mockito.nullable(MonitoringDocumentSearchRequest.class));
}
위의 코드에서 Spring과 Mockito는 MonitoringDocumentsRepository 객체를 프록시하려고 시도하지만 Spring이 먼저 시작되어 findMonitoringDocuments 메소드를 실제로 호출합니다. 리포지토리 객체에 스파이를 넣은 직후 코드를 디버깅하면 디버거 내부에서 다음과 같이 보입니다.
repository = MonitoringDocumentsRepository$$EnhancerBySpringCGLIB$$MockitoMock$
구조에 @SpyBean
@Autowired
주석 대신 주석을 사용 @SpyBean
하면 위의 문제를 해결할 것입니다 .SpyBean 주석은 리포지토리 객체도 주입하지만 Mockito가 먼저 프록시하고 디버거 내에서 다음과 같이 보입니다.
repository = MonitoringDocumentsRepository$$MockitoMock$$EnhancerBySpringCGLIB$
그리고 여기 코드가 있습니다 :
@SpyBean
private MonitoringDocumentsRepository repository
void test(){
Mockito.doReturn(docs1, docs2)
.when(repository).findMonitoringDocuments(Mockito.nullable(MonitoringDocumentSearchRequest.class));
}
답변
스파이가 원래 메서드를 호출해야하는 또 다른 이유를 찾았습니다.
누군가는 final
수업 을 조롱하려는 아이디어를 가지고 다음 에 대해 발견했습니다 MockMaker
.
이 기능은 현재 메커니즘과 다르게 작동하며 다른 제한 사항이 있으며 경험과 사용자 피드백을 수집하려면이 기능을 명시 적으로 활성화해야 사용할 수 있습니다.
src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
단일 행을 포함하는 파일을 작성하여 mockito 확장 메커니즘을 통해 수행 할 수 있습니다 .mock-maker-inline
해당 파일을 병합하여 내 컴퓨터로 가져온 후 테스트에 실패했습니다.
방금 줄 (또는 파일)을 제거하고 spy()
일했습니다.
답변
파티에 늦었지만 위의 솔루션이 효과가 없었으므로 0.02 $를 공유했습니다.
Mokcito 버전 : 1.10.19
MyClass.java
private int handleAction(List<String> argList, String action)
테스트
MyClass spy = PowerMockito.spy(new MyClass());
다음은 나를 위해 작동하지 않았습니다 (실제 방법이 호출되었습니다).
1.
doReturn(0).when(spy , "handleAction", ListUtils.EMPTY_LIST, new String());
2.
doReturn(0).when(spy , "handleAction", any(), anyString());
삼.
doReturn(0).when(spy , "handleAction", null, null);
다음 작업 :
doReturn(0).when(spy , "handleAction", any(List.class), anyString());