سؤال

I try to mock this method, but I can´t figure out how to structure this... I use Mockito and jUnit.

Is there some way to do this in a easy way?

Many thanks.


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

        if (HSBC_PAYREC.equals(columnId)) {
            String s = (String) getColumnValue(row, "Pay/Rcv", errors);
            if (s != null) {
                if (s.equals("Pay")) {
                    return "Receive";
                }
            }
            return "";
        }
}
هل كانت مفيدة؟

المحلول

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 "";
    }
  }
}

نصائح أخرى

In order to mock the recursive call, you could use an indirect recursion, like this:

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 "";
   }
}

You can then mock the indirectGetColumnValue method. I am not saying that this is the preferred method, as you make your code less readable by introducing this indirect recursion call. But, it's one way to test it.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top