Незаконченное раскорчевки обнаружить в 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;
    }
}
1 85

1 ответ:

вы гнездитесь насмешливо внутри насмешки. Ты звонишь getSomeList(), который делает некоторые насмешки, прежде чем вы закончите насмешки для MyMainModel. Мокито не любит, когда ты так делаешь.

заменить

@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:

  • Mock метод mainModel.getList() называется
  • статический метод when называется
  • метод thenReturn о строка
    Mockito.when(mainModel.getList()).thenReturn(getSomeList());
    

    вызывает следующие взаимодействия с Mockito:

    1. макет метод mainModel.getList() называется
    2. статический метод when is звонил,
    3. новая mock на SomeModel создается (внутри getSomeList()),
    4. макет метод model.getName() называется

    в этот момент Мокито запутывается. Он думал, что ты издеваешься mainModel.getList(), но теперь вы говорите, что хотите высмеять model.getName() метод. В Mockito, похоже, вы делаете следующее:

    when(mainModel.getList());
    // ...
    when(model.getName()).thenReturn(...);
    

    это выглядит глупо Mockito как он не может быть уверен, что вы делаете с mainModel.getList().

    Примечание. чтобы мы не добрались до thenReturn вызов метода, так как JVM должен оценить параметры этого метода, прежде чем он сможет вызвать метод. В этом случае это означает вызов getSomeList() метод.

    как правило, это плохое проектное решение полагаться на статическое состояние, как это делает Mockito, потому что это может привести к случаям, когда нарушается принцип наименьшего удивления. Тем не менее, дизайн Mockito действительно делает для ясной и выразительной насмешки, даже если это приводит к удивлению иногда.

    наконец, последние версии Mockito добавляют дополнительную строку к сообщению об ошибке выше. Эта дополнительная строка указывает, что вы можете быть в той же ситуации, что и этот вопрос:

    3: вы заглушаете поведение другого макета внутри перед инструкцией "thenReturn", если она завершена