Because you're testing the system under test, it doesn't really ever make sense to mock the system under test. I think it's fair to say that this includes mocking recursive calls to the system under test. (Besides being philosophically very strange, you might have a very hard time ensuring that you're calling the unmocked version from the test while ensuring the unmocked version calls the mocked version when it tries to call itself.) Your best bet is to restructure your test so that the recursive behavior is part of your expected behavior.
That said, and though it does make the code harder to follow, you do have two alternatives. One involves a partial mock:
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);
}
And in the test:
@Test public void yourTest() {
SystemUnderTest yourSystemUnderTest = Mockito.spy(new SystemUnderTest());
doReturn(yourMockedValue).when(yourSystemUnderTest).getColumnValueRecursively(
/* your recursive base case */);
// ...
}
Technically, I suppose you could do that without creating the indirect recursion, but then you're switching behavior based on parameters and that makes it harder to ensure your test is valid. Your other option is equally tricky:
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 "";
}
}
}