例如:
public class NumberService {
public boolean isNaturalNumber(int num) {
return num > 0;
}
public String getClassificationInfo(int num) {
return isNaturalNumber(num) ? num + "is a natural number" : num + "is not a natural number";
}
}
这里有两个公共方法,而getClassificationInfo
方法称为isNaturalNumber
方法。
在测试isNaturalNumber
时嘲笑getClassificationInfo
是一个好习惯吗?
像这样:
@RunWith(MockitoJUnitRunner.class)
public class NumberServiceTest {
@Spy
private NumberService numberService;
@Test
public void test_getClassificationInfo_when_is_natural_number() {
int num = generateInt();
doReturn(true).when(numberService).isNaturalNumber(num);
String classificationInfo = numberService.getClassificationInfo(num);
assertThat(classificationInfo).isEqualTo(num + "is a natural number");
}
@Test
public void test_getClassificationInfo_when_is_not_natural_number() {
int num = generateInt();
doReturn(false).when(numberService).isNaturalNumber(num);
String classificationInfo = numberService.getClassificationInfo(num);
assertThat(classificationInfo).isEqualTo(num + "is not a natural number");
}
// the other test for isNaturalNumber
private int generateInt() {
return new Random().nextInt();
}
}
在这种特殊情况下,模拟调用的方法没有意义。然而,这不仅仅是因为它是同一类的方法。实际上,有时会引入同一类的方法以允许它们被模拟。例如,如果在您的类中处理通过文件I / O获得的某些数据,则可以将文件I / O隔离到自己的方法中。然后,您可以使用模拟版本的文件I / O方法测试数据处理。
然而,在这种情况下,没有充分的理由在isNaturalNumber
的测试中模拟getClassificationInfo
:方法isNaturalNumber
具有确定性行为并且不会导致不可接受的长执行时间。通过模拟isNaturalNumber
故意在getClassificationInfo
的一个测试中表现错误的情况,你似乎也不太可能获得更多。
你不必粗暴地模仿一切。例如,您也不会模拟标准库数学函数,如sin
或cos
,因为它们在大多数情况下也不会导致问题。嘲笑应该是有原因的。因此,如果您考虑模拟函数或方法,您应该知道要解决的问题。如果没有问题要解决,请不要嘲笑。
不是它不是很好的做法,因为我们应该模拟其他模块/类对象所涉及的存根。
例如:
public class A{
private B aObj;
public void aDoingSomeBWork(){
aObj.someMethod();
someLogic();
}
private/public/any modifier void someLogic(){
//some logic
}
}
public class B{
public void someMethod(){}
}
然后你应该模拟B的someMethod(),但不应该是A的someLogic(),因为你是单元测试A的aDoingSomeBWork()方法。如果你模拟someLogic();在单元测试中,可能存在代码中断的情况。