Java 如何测试和模拟递归方法?

Java 如何测试和模拟递归方法?,java,mockito,Java,Mockito,我试图模仿这个方法,但我不知道如何构造这个。。。 我使用Mockito和jUnit 有没有简单的方法可以做到这一点 非常感谢 为了模拟递归调用,可以使用间接递归,如下所示: private Object indirectGetColumnValue(ReportRow row, String columnId, Vector errors) { return getColumnValue(row, "Pay/Rcv", errors); } public Object getColu

我试图模仿这个方法,但我不知道如何构造这个。。。 我使用Mockito和jUnit

有没有简单的方法可以做到这一点

非常感谢



为了模拟递归调用,可以使用间接递归,如下所示:

private Object indirectGetColumnValue(ReportRow row, String columnId, Vector errors) {
    return getColumnValue(row, "Pay/Rcv", errors);
}

public Object getColumnValue(ReportRow row, String columnId, Vector errors) {

if (HSBC_PAYREC.equals(columnId)) {
    String s = (String) indirectGetColumnValue(row, "Pay/Rcv", errors);
    if (s != null) {
        if (s.equals("Pay")) {
            return "Receive";
        }
        if (s.equals("Receive")) {
            return "Pay";
        }
    }
    return "";
   }
}
然后可以模拟
indirectGetColumnValue
方法。我并不是说这是首选方法,因为通过引入这种间接递归调用,代码的可读性会降低。但是,这是测试它的一种方法。

因为您正在测试被测系统,所以模拟被测系统是毫无意义的。我认为公平地说,这包括模拟对测试系统的递归调用。(除了在哲学上非常奇怪之外,您可能很难确保在测试中调用未修改的版本,同时确保未修改的版本在尝试调用自身时调用模拟版本。)最好的办法是重新构造测试,使递归行为成为预期行为的一部分。

也就是说,虽然这确实使代码更难遵循,但您确实有两种选择。其中一个涉及部分模拟:

public Object getColumnValue(ReportRow row, String columnId, Vector errors) {
  if (HSBC_PAYREC.equals(columnId)) {
    String s = (String) getColumnValueRecursively(row, "Pay/Rcv", errors);
    if (s != null) {
      if (s.equals("Pay")) {
        return "Receive";
      }
      if (s.equals("Receive")) {
        return "Pay";
      }
      return "";
    }
  }
}

/** For testing. */
Object getColumnValueRecursively(ReportRow row, String columnId, Vector errors) {
  return getColumnValue(row, columnId, errors);
}
在测试中:

@Test public void yourTest() {
  SystemUnderTest yourSystemUnderTest = Mockito.spy(new SystemUnderTest());
  doReturn(yourMockedValue).when(yourSystemUnderTest).getColumnValueRecursively(
      /* your recursive base case */);
  // ...
}
从技术上讲,我认为您可以在不创建间接递归的情况下实现这一点,但是您正在根据参数切换行为,这使得确保测试有效性变得更加困难。你的另一个选择同样棘手:

SystemUnderTest recursiveInstance = this; // replace with a mock within test

public Object getColumnValue(ReportRow row, String columnId, Vector errors) {
  if (HSBC_PAYREC.equals(columnId)) {
    String s = (String) recursiveInstance.getColumnValue(row, "Pay/Rcv", errors);
    if (s != null) {
      if (s.equals("Pay")) {
        return "Receive";
      }
      if (s.equals("Receive")) {
        return "Pay";
      }
      return "";
    }
  }
}

这里有问题吗?
SystemUnderTest recursiveInstance = this; // replace with a mock within test

public Object getColumnValue(ReportRow row, String columnId, Vector errors) {
  if (HSBC_PAYREC.equals(columnId)) {
    String s = (String) recursiveInstance.getColumnValue(row, "Pay/Rcv", errors);
    if (s != null) {
      if (s.equals("Pay")) {
        return "Receive";
      }
      if (s.equals("Receive")) {
        return "Pay";
      }
      return "";
    }
  }
}