Mockito UnfinishedStubbingException

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

...
OperationNode child = getNode(Operation.ADD);
child.insertNode(getConstantNode(getIntegerValue(2));
...

 private ConstantNode getConstantNode(NumericalValue value){
    ConstantNode node = Mockito.mock(ConstantNode.class);
    Mockito.when(node.evaluate()).thenReturn(value);
    Mockito.when(node.toString()).thenReturn(value.toString());
    return node;
}

private IntegerValue getIntegerValue(int number) {
   IntegerValue integerValue = Mockito.mock(IntegerValue.class);
   Mockito.when(integerValue.getValue()).thenReturn(number);
   Mockito.when(integerValue.toString()).thenReturn(Integer.toString(number));
   return integerValue;
}

На одном из форумов я прочитал о том, что нельзя отправлять макет через конструктор другого макета, поскольку Mockito может запутаться с вызовами макета, поэтому я попробовал следующее:

NumericalValue value = getIntegerValue(2);
child.insertNode(getConstantNode(value));

Но безрезультатно. Я удостоверяюсь, что вызываются только методы toString() и getValue(), потому что это единственные методы, которые есть у класса. Я не понимаю, что происходит.

Я также пытался использовать макеты отдельно, чтобы увидеть, сделал ли я что-то не так:

child.insertNode(new ConstantNode(getIntegerValue(2)));

Это работает отлично.

child.insertNode(getConstantNode(new IntegerValue(2)));

Это тоже хорошо работает.


person Chayemor    schedule 21.03.2013    source источник
comment
известная проблема https://code.google.com/p/mockito/issues/detail?id=53   -  person Sajan Chandran    schedule 21.03.2013
comment
Активная ссылка: code.google.com/p/mockito/issues/detail. ?id=53   -  person Duncan Jones    schedule 24.06.2014
comment
Насмешки, возвращающие насмешки, обычно являются запахом кода.   -  person haventchecked    schedule 07.01.2019


Ответы (4)


Из того, что я прочитал в «Выпуске 53» mockito (https://code.google.com/p/mockito/issues/detail?id=53), в моем коде возникла проблема из-за используемой в Mockito среды проверки. Именно следующий код вызывал исключение как таковое.

private ConstantNode getConstantNode(NumericalValue value){
    ConstantNode node = Mockito.mock(ConstantNode.class);
    Mockito.when(node.evaluate()).thenReturn(value);
    Mockito.when(node.toString()).thenReturn(value.toString());
    return node;
}

Если вы помните из моего кода, значение параметра ТАКЖЕ МАКЕТ, поэтому, когда value.toString() вызывается на thenReturn(), я считаю (и кто-нибудь, пожалуйста, поправьте меня, если я ошибаюсь), что среда проверки запускается и гарантирует, что каждый " когда" был thenReturn() вызван/проверен/и т.д. Так что, если это произойдет, Mockito.when(node.toString()).thenReturn(value.toString() не будет проверен, потому что он не вернулся из valute.toString(), с которого началась вся цепочка "проверить все".

Как я это исправил:

private ConstantNode getConstantNode(NumericalValue value){
    ConstantNode node = Mockito.mock(ConstantNode.class);
    Mockito.when(node.evaluate()).thenReturn(value);

    String numberToString = value.toString();

    Mockito.when(node.toString()).thenReturn(numberToString);
    return node;
}

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

Спасибо за помощь.

person Chayemor    schedule 21.03.2013
comment
Спасибо! Наконец-то я начинаю понимать эту странную проблему. - person Piotr Sobczyk; 24.07.2013

В этом вопросе уже опубликовано несколько хороших исправлений, но для тех, у кого все еще есть проблемы с его пониманием, подумайте о порядке, в котором Java вызывает все эти методы. Согласно Спецификации языка Java, Java оценивает каждый параметр метода слева направо перед вызов метода:

  1. integerValue.getValue(), который записывает Mockito
  2. when, где Mockito берет последний звонок (к integer.getValue) и начинает настройку заглушки
  3. value.toString, который является насмешливым звонком, который записывает Mockito
  4. thenReturn на стаббере

Mockito жалуется именно потому, что вызов макета, шаг 3, происходит после шага 2 (when), но до шага 4 (thenReturn), в результате чего платформа проверки жалуется на затыкать. Джой, ваш ответ перемещает неприятный шаг 3 до шага 1, и это нормально; Саджан полностью удаляет его из утверждения, что тоже нормально.

person Jeff Bowman    schedule 22.03.2013

думаю проблема в линии

Mockito.when(node.toString()).thenReturn(value.toString()); в методе getConstantNode

Попробуйте удалить строку и проверьте, работает ли она. Может быть, вы можете сделать что-то вроде

int num = 2;
child.insertNode(getConstantNode(getIntegerValue(num), num);
...

 private ConstantNode getConstantNode(NumericalValue value){
    ConstantNode node = Mockito.mock(ConstantNode.class);
    Mockito.when(node.evaluate()).thenReturn(value);
    Mockito.when(node.toString()).thenReturn(Integer.toString(number));
    return node;
}

private IntegerValue getIntegerValue(int number) {
   IntegerValue integerValue = Mockito.mock(IntegerValue.class);
   Mockito.when(integerValue.getValue()).thenReturn(number);
   return integerValue;
}
person Sajan Chandran    schedule 21.03.2013
comment
Откуда тогда число? - person AHungerArtist; 21.03.2013
comment
Это решило проблему исключения, но я до сих пор не понимаю динамику того, почему это происходит. Я прочитал ссылку на проблему, размещенную в первом комментарии, но я все еще не понимаю. - person Chayemor; 22.03.2013

Я думаю, что это проблема с порядком вызовов и проверкой Mockito Framework. Попробуйте это и посмотрите, поможет ли это:

...
OperationNode child = getNode(Operation.ADD);
IntegerValue value = getIntegerValue(2);
ConstantNode node =  Mockito.mock(ConstantNode.class);
Mockito.when(node.evaluate()).thenReturn(value);
Mockito.when(node.toString()).thenReturn(value.toString());
child.insertNode(node);

...

private IntegerValue getIntegerValue(int number) {
   IntegerValue integerValue = Mockito.mock(IntegerValue.class);
   Mockito.when(integerValue.getValue()).thenReturn(number);
   Mockito.when(integerValue.toString()).thenReturn(Integer.toString(number));
   return integerValue;
}

Источник: https://code.google.com/p/mockito/issues/detail?id=53

person StuPointerException    schedule 21.03.2013
comment
Разве это не то же самое, только без метода? ... В любом случае, я пробовал, бесполезно. - person Chayemor; 22.03.2013