[java] Mockito에서 미완성 스터 빙 감지
테스트를 실행하는 동안 다음과 같은 예외가 발생합니다. 조롱을 위해 Mockito를 사용하고 있습니다. Mockito 라이브러리가 언급 한 힌트는 도움이되지 않습니다.
org.mockito.exceptions.misusing.UnfinishedStubbingException:
Unfinished stubbing detected here:
-> at com.a.b.DomainTestFactory.myTest(DomainTestFactory.java:355)
E.g. thenReturn() may be missing.
Examples of correct stubbing:
when(mock.isOk()).thenReturn(true);
when(mock.isOk()).thenThrow(exception);
doThrow(exception).when(mock).someVoidMethod();
Hints:
1. missing thenReturn()
2. you are trying to stub a final method, you naughty developer!
at a.b.DomainTestFactory.myTest(DomainTestFactory.java:276)
..........
테스트 코드에서 DomainTestFactory
. 다음 테스트를 실행하면 예외가 나타납니다.
@Test
public myTest(){
MyMainModel mainModel = Mockito.mock(MyMainModel.class);
Mockito.when(mainModel.getList()).thenReturn(getSomeList()); // Line 355
}
private List<SomeModel> getSomeList() {
SomeModel model = Mockito.mock(SomeModel.class);
Mockito.when(model.getName()).thenReturn("SomeName"); // Line 276
Mockito.when(model.getAddress()).thenReturn("Address");
return Arrays.asList(model);
}
public class SomeModel extends SomeInputModel{
protected String address;
protected List<SomeClass> properties;
public SomeModel() {
this.Properties = new java.util.ArrayList<SomeClass>();
}
public String getAddress() {
return this.address;
}
}
public class SomeInputModel{
public NetworkInputModel() {
this.Properties = new java.util.ArrayList<SomeClass>();
}
protected String Name;
protected List<SomeClass> properties;
public String getName() {
return this.Name;
}
public void setName(String value) {
this.Name = value;
}
}
답변
조롱 안에 조롱하고 있습니다. 에 getSomeList()
대한 조롱을 마치기 전에을 조롱하는 중입니다 MyMainModel
. Mockito는 당신이 이것을 할 때 그것을 좋아하지 않습니다.
바꾸다
@Test
public myTest(){
MyMainModel mainModel = Mockito.mock(MyMainModel.class);
Mockito.when(mainModel.getList()).thenReturn(getSomeList()); --> Line 355
}
와
@Test
public myTest(){
MyMainModel mainModel = Mockito.mock(MyMainModel.class);
List<SomeModel> someModelList = getSomeList();
Mockito.when(mainModel.getList()).thenReturn(someModelList);
}
이것이 왜 문제를 일으키는 지 이해하려면 Mockito의 작동 방식에 대해 약간 알아야하고 Java에서 평가되는 표현식 및 명령문의 순서를 알아야합니다.
Mockito는 소스 코드를 읽을 수 없으므로 요청한 내용을 파악하려면 정적 상태에 크게 의존합니다. 모의 객체에서 메소드를 호출하면 Mockito는 호출의 세부 사항을 내부 호출 목록에 기록합니다. 이 when
메소드는 마지막 호출을 목록에서 읽고이 호출을 OngoingStubbing
리턴 하는 오브젝트 에 기록 합니다.
라인
Mockito.when(mainModel.getList()).thenReturn(someModelList);
Mockito와 다음과 같은 상호 작용을 일으 킵니다.
- 모의 메서드
mainModel.getList()
를 호출 - 정적 메소드
when
가 호출됩니다. - 메소드
thenReturn
가OngoingStubbing
리턴 한 오브젝트 에서 메소드 가 호출됩니다when
.
thenReturn
방법은 다음을 통해 수신 된 모의 지시 할 OngoingStubbing
받는 임의의 적절한 통화 처리하는 방법을 getList
반환하는 방법 someModelList
.
실제로 Mockito는 코드를 볼 수 없으므로 다음과 같이 조롱을 작성할 수 있습니다.
mainModel.getList();
Mockito.when((List<SomeModel>)null).thenReturn(someModelList);
이 스타일은 읽기가 다소 null
어렵 습니다. 특히이 경우에는 캐스팅해야하기 때문에 Mockito와 동일한 시퀀스의 상호 작용을 생성하며 위의 라인과 동일한 결과를 얻을 수 있습니다.
그러나 라인
Mockito.when(mainModel.getList()).thenReturn(getSomeList());
Mockito와 다음과 같은 상호 작용을 일으 킵니다.
- 모의 메서드
mainModel.getList()
를 호출 - 정적 메소드
when
가 호출됩니다. - 새
mock
의SomeModel
생성 (내부getSomeList()
) - 모의 메서드
model.getName()
를 호출
이 시점에서 Mockito는 혼란스러워합니다. 그것은 당신이 조롱 mainModel.getList()
하고 있다고 생각 했지만, 지금 당신은 당신이 model.getName()
방법 을 조롱하고 싶다고 말하고 있습니다 . Mockito에게는 다음을 수행하는 것처럼 보입니다.
when(mainModel.getList());
// ...
when(model.getName()).thenReturn(...);
Mockito
당신이하고있는 일을 확신 할 수 없으므로 어리석게 보입니다 mainModel.getList()
.
thenReturn
JVM이 메소드를 호출하기 전에이 메소드에 대한 매개 변수를 평가해야 하므로 메소드 호출에 도달하지 않았습니다 . 이 경우 이는 getSomeList()
메소드 호출을 의미합니다 .
일반적으로 Mockito와 마찬가지로 정적 상태에 의존하는 것은 좋지 않은 설계 결정입니다. 이는 최소 놀랍게도의 원칙을 위반하는 사례로 이어질 수 있기 때문입니다. 그러나 Mockito의 디자인은 때로는 놀랍게도 명확하고 표현적인 조롱을합니다.
마지막으로, Mockito의 최신 버전은 위의 오류 메시지에 추가 줄을 추가합니다. 이 추가 행은이 질문과 같은 상황에있을 수 있음을 나타냅니다.
3 : 완료되면 ‘thenReturn’명령 전에 다른 모의 동작을 스텁합니다.
답변
org.mockito.exceptions.misusing.UnfinishedStubbingException:
Unfinished stubbing detected here:
E.g. thenReturn() may be missing.
void 메소드를 조롱하려면 아래를 시도하십시오.
//Kotlin Syntax
Mockito.`when`(voidMethodCall())
.then {
Unit //Do Nothing
}