在同一个类中模拟其他公共方法是否是一个好习惯

时间:2018-10-11 03:28:28

标签: java unit-testing mocking

例如:

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

2 个答案:

答案 0 :(得分:1)

在这种特殊情况下,模拟调用的方法没有任何意义。但是,这不仅仅是因为它是同一类的方法。实际上,有时会专门引入相同类的方法来模拟它们。例如,如果在您的类中处理通过文件I / O获得的某些数据,则可以将文件I / O隔离到其自身的方法中。然后,您可以使用模拟版本的文件I / O方法来测试数据处理。

但是,在这种情况下,没有充分的理由在isNaturalNumber的测试中模拟getClassificationInfo:方法isNaturalNumber具有确定性的行为,不会导致执行时间过长。通过模拟isNaturalNumbergetClassificationInfo的一项测试中有意表现为错误的情况,您似乎不太可能获得很多收益。

您不必教条地嘲笑一切。例如,您也不模拟sincos之类的标准库数学函数,因为它们在大多数情况下也不会引起问题。模拟是有原因的。因此,如果您考虑模拟函数或方法,则应该知道要解决的问题。如果没有问题要解决,请不要嘲笑。

答案 1 :(得分:0)

否这不是一个好习惯,因为我们应该在涉及其他模块/类对象的地方模拟存根。

例如:

Transformation

然后,您应该模拟B的someMethod(),而不应该模拟A的someLogic(),因为您正在对A的aDoingSomeBWork()方法进行单元测试。如果您模拟someLogic();在单元测试中,则可能会发生代码中断的情况。