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;
    }
}

IM通过使用Mockito编写验证器iSparent方法的测试用例。

公共类ValtorAtest {

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),因为嘲笑人类集在call human.isparent();

时返回true

我使用 mockito.verifyZeroInteractions(),但它说失败据我了解, mockito.verifyZeroInteractions()通过所有测试检查。不仅用于特定的方法调用。

我想知道是否有某种方法可以验证某些情况下的方法,并且在同一测试方法中,方法对相同的情况进行了调用。或者我应该在一种测试方法中练习测试一个方案。

这是一个很好的做法,最好是"每一种测试方法"(请参阅每个功能/方法我应该写多少个单元测试?)

从技术上讲,仍然可以使用Mockito.reset(...)重置模拟,但是这是官方文档对此所说的:

Smart Mockito用户几乎不使用此功能,因为他们知道这可能是测试不良的迹象。 通常,您无需重置模拟,只需为每种测试方法创建新的模拟。

而不是reset(),请考虑在冗长的,过度指定的测试上写作简单,小且集中的测试方法。在测试方法中间,第一个潜在的代码气味是reset()。这可能意味着您正在测试太多。遵循您的测试方法的耳语:"请让我们小小的专注于单一行为"。

请参阅https://static.javadoc.io/org.mockito/mockito-core/2.9.0/org/mockito/mockito/mockito.html#17

验证方法可以接受第二个参数,您可以在其中指定调用该方法的次数。您可以用它来说该方法从未被调用,一次调用,两次等。

例如:

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/mockito.html#4

我想指出,这个问题严重滥用模拟,用于测试可以轻松,干净地测试而无需任何模拟的事物。

这是测试的样子:

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)应 not 被模拟。

相关内容

  • 没有找到相关文章

最新更新