1

I'm trying to test my Utils class. Some of the methods use other class methods. I want to mock the internal methods use so the test will assume they work (in order to make it real Unit test, which test the specific method).

I want to test 'buildUrl' method:

 public static String buildUrl(String path, List<Pair> queryParams, DateFormat dateFormat) {
    final StringBuilder url = new StringBuilder();
    url.append(path);

    if (queryParams != null && !queryParams.isEmpty()) {
        // support (constant) query string in `path`, e.g. "/posts?draft=1"
        String prefix = path.contains("?") ? "&" : "?";
        for (Pair param : queryParams) {
            if (param.getValue() != null) {
                if (prefix != null) {
                    url.append(prefix);
                    prefix = null;
                } else {
                    url.append("&");
                }
                String value = Utils.parameterToString(param.getValue(), dateFormat);
                url.append(Utils.escapeString(param.getName())).append("=").append(Utils.escapeString(value));
            }
        }
    }

    return url.toString();
}

BuildUrl uses 'parameterToString' (and others) which I want to mock for the test. So I tried something like this:

 @Test
public void testBuildUrl(){
    Utils util = new Utils();
    Utils utilSpy = Mockito.spy(util);
    Mockito.when(utilSpy.parameterToString("value1",new RFC3339DateFormat())).thenReturn("value1");
    List<Pair> queryParams = new ArrayList<Pair>();
    queryParams.add(new Pair("key1","value1"));
    String myUrl = utilSpy.buildUrl("this/is/my/path", queryParams, new RFC3339DateFormat());
    assertEquals("this/is/my/path?key1=value1&key2=value2", myUrl);
}

But I'm getting MissingMethodInvocationException from Mockito. So my question is actually - how to mock a method that has been invoked within the tested method, and what's wrong with my test. Thanks.

Rufi
  • 2,529
  • 1
  • 20
  • 41
user2880391
  • 2,683
  • 7
  • 38
  • 77

2 Answers2

0

You cannot mock / spy static invocations using standard Mockito.

You will have to use Powermockito and something to the following:

@RunWith(PowerMockRunner.class)
@PrepareForTest(Utils.class)    
public class MyClassTest{

    @Test
    public void testBuildUrl(){
         PowerMockito.mockStatic(Utils.class);

         // mock the static method to return certain values
         Mockito.when(Utils.parameterToString("value1",new RFC3339DateFormat()))
             .thenReturn("value1");
         Mockito.when(Utils.escapeString(anyString()).thenReturn(desiredResult);

       // rest of test code
    }

Here is some more stuff to read through -> powermockito static

Community
  • 1
  • 1
Maciej Kowalski
  • 25,605
  • 12
  • 54
  • 63
0

I want to mock the internal methods use so the test will assume they work (in order to make it real Unit test, which test the specific method).

UnitTests do not test specific methods.

UnitTests test public observable behavior of the code under test.


If you feel you should mock some of the methods this could be a sign that your design needs improvement. There is no need to make utility methods static and maybe your Class under test has to much responsibilities.

Of cause PowerMock will overcome the problems in your test but IMHO the use of PowerMock is a surrender to bad design.

Timothy Truckle
  • 15,071
  • 2
  • 27
  • 51