Mockito, убедитесь, что строка не выполняется для какого-либо условия внутри одного метода тестирования

Я пишу модульный тест, используя testng и mockito. Обычно я вызываю один метод несколько раз внутри одного и того же метода тестирования, используя разные значения / условия для проверки всех сценариев.

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

Просмотрите код ниже.

public class Human {

    private String name;
    private boolean parent;
    private List<Human> childs = new ArrayList<>();

    public String getName() {
        return name;
    }

    public boolean isParent() {
        return parent;
    }

    public void setParent(boolean parent) {
        this.parent = parent;
    }

    public void addChild(List<Human> childs) {
        this.childs = childs;
    }

    public List<Human> getChilds() {
        return childs;
    }


}

public class Validator {
    public boolean isParent(Human human) {
        if (null == human) {
            return false;
        }
        if (human.isParent()) {
            return true;
        }
        if (human.getChilds().size() > 0) {
            return true;
        }
        return false;
    }
}

Я пишу тестовый пример для метода Validator isParent с помощью mockito.

public class ValidatorTest {

public void testIsParent() throws Exception {
    Validator validator = Mockito.spy(new Validator());
    Human human = Mockito.mock(Human.class);
    Mockito.when(human.isParent()).thenReturn(false);
    boolean isParent = validator.isParent(human);
    Mockito.verify(human).getChilds();

    Mockito.when(human.isParent()).thenReturn(true);
    isParent = validator.isParent(human);
    Mockito.verify(human).getChilds();


}

Здесь я хочу убедиться, что getChilds () никогда не вызывает второй вызов метода для validator.isParent (human), потому что издеваемый человеческий набор возвращает true при вызове human.isParent ();

Я использовал Mockito.verifyZeroInteractions (), но он говорит об ошибке. Насколько я понимаю, проверка Mockito.verifyZeroInteractions () во всех тестах. не только для вызова конкретного метода.

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


person Chamly Idunil    schedule 31.08.2017    source источник
comment
1 сценарий на каждый метод тестирования. 1-й вы проверяете, является ли человек родителем, и возвращаете истину, а ваш 2-й метод тестирования должен быть противоположным   -  person XtremeBaumer    schedule 31.08.2017


Ответы (3)


Рекомендуется использовать «один сценарий на один метод тестирования» (см. Сколько модульных тестов я должен написать для каждой функции / метода?)

Технически все еще можно сбросить моки с помощью Mockito.reset(...), но об этом говорится в официальной документации:

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

Вместо reset() рассмотрите возможность написания простых, небольших и целенаправленных методов тестирования вместо длинных, чрезмерно определенных. Первый потенциальный запах кода - это reset() в середине метода тестирования. Вероятно, это означает, что вы слишком много тестируете. Следуйте шепоту ваших методов тестирования: «Пожалуйста, держите нас маленькими и сосредотачивайтесь на одном поведении».

См. https://static.javadoc.io/org.mockito/mockito-core/2.9.0/org/mockito/Mockito.html#17

person Maxim Ponomarev    schedule 31.08.2017
comment
Спасибо за ответ и совет. здесь я использовал mockito.reset и попробовал Mockito.verifyZeroInteractions (). но его падает. - person Chamly Idunil; 31.08.2017
comment
Mockito также говорит, что объекты значений (Human) не должны подвергаться издевательствам. Также следует с подозрением относиться к частичному издевательству (шпионы). - person Rogério; 04.09.2017

Метод verify может принимать второй аргумент, в котором вы можете указать, сколько раз был вызван метод. Вы можете использовать это, чтобы сказать, что метод никогда не вызывался, вызывался один раз, дважды и т. Д.

Например:

import static org.mockito.Mockito.never;

...

public void testIsParent() throws Exception {
    Validator validator = Mockito.spy(new Validator());
    Human human = Mockito.mock(Human.class);
    Mockito.when(human.isParent()).thenReturn(false);
    boolean isParent = validator.isParent(human);
    Mockito.verify(human).getChilds();

    Mockito.when(human.isParent()).thenReturn(true);
    isParent = validator.isParent(human);
    Mockito.verify(human, never()).getChilds();

}

Документация для этого находится здесь: http://static.javadoc.io/org.mockito/mockito-core/2.9.0/org/mockito/Mockito.html#4

person robjwilkins    schedule 31.08.2017
comment
Это дает ошибку Никогда не хотел здесь: - ›at {class} Но вызывается здесь: - person Chamly Idunil; 31.08.2017
comment
@ChamlyIdunil, это потому, что метод вызывается ?! - person robjwilkins; 31.08.2017
comment
Зачем кому-то писать такой ужасный тест, если он может быть намного чище без mock'ов, при этом следуя советам самого Mockito на как писать хорошие тесты? - person Rogério; 04.09.2017
comment
@ Rogério Я не писал тест, я отвечал на вопрос о том, как проверить, сколько раз вызывали макет - person robjwilkins; 05.09.2017

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

Вот должны выглядеть тесты:

public class ValidatorTest {
    final Validator sut = new Validator();

    @Test
    public void checkThatNoHumanIsNotAParent() {
        boolean isParent = sut.isParent(null);

        assertFalse(isParent);
    }

    @Test
    public void checkHumanThatIsNotAParent() {
        Human notAParent = new Human();

        boolean isParent = sut.isParent(notAParent);

        assertFalse(isParent);
    }

    @Test
    public void checkParentHumanWithNoChildIsAParent() {
        Human parentWithNoChildren = new Human();
        parentWithNoChildren.setParent(true);

        boolean isParent = sut.isParent(parentWithNoChildren);

        assertTrue(isParent);
    }

    @Test
    public void checkHumanNotMarkedAsParentButWithChildIsAParent() {
        Human humanWithChildren = new Human();
        Human child = new Human();
        humanWithChildren.addChild(child);

        boolean isParent = sut.isParent(humanWithChildren);

        assertTrue(isParent);
    }
}

Эти тесты полностью проверяют все четыре сценария. Они явно намного лучше, чем версия, в которой используется насмешка. Наконец, обратите внимание, что документация Mockito (на странице о том, как писать хорошие тесты) также говорит, что объекты значений (такие как Human) не должны подвергаться издевательствам.

person Rogério    schedule 04.09.2017
comment
В вопросе четко сказано, что это пример, а не реальный код. - person Maxim Ponomarev; 04.09.2017
comment
@MaximPonomarev Тогда он должен показать пример, в котором использование насмешек действительно имеет смысл ... - person Rogério; 04.09.2017