我正在使用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;
}
}
我使用mockito为Validator isParent方法编写测试用例。
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)的第二个方法调用,因为当调用human.isParent()时,mocked human set返回true;
我使用了 Mockito.verifyZeroInteractions(),但它说失败了 据我所知 Mockito.verifyZeroInteractions()检查所有测试。不仅适用于特定的方法调用。
我想知道是否有一些方法可以验证方法是否在同一测试方法中调用某些情况和方法调用相同的情况。 或者我应该在一种测试方法中练习测试一种情况。
答案 0 :(得分:0)
一个好的做法是每一个测试方法有一个场景&#34; (见How many unit tests should I write per function/method?)
从技术上讲,它仍然可以使用Mockito.reset(...)
重置模拟,但这正是官方文档中所说的:
Smart Mockito用户几乎不使用此功能,因为他们知道这可能是测试不佳的迹象。 通常,您不需要重置模拟,只需为每种测试方法创建新的模拟。
请考虑在冗长,过度指定的测试中编写简单,小巧且专注的测试方法,而不是
reset()
。在测试方法的中间,第一个潜在的代码气味是reset()
。这可能意味着你进行了太多的测试。按照你的测试方法的低语:&#34;请保持我们的小和&amp;专注于单一行为&#34;。
请参阅https://static.javadoc.io/org.mockito/mockito-core/2.9.0/org/mockito/Mockito.html#17
答案 1 :(得分:-1)
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
答案 2 :(得分:-1)
我想指出,这个问题严重滥用嘲弄,用于测试可以轻松,干净地进行测试而无需任何嘲笑的内容。
这个是测试的样子:
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
)应该不被模拟。