Testing private static method that internally uses another private static method in Java

Viewed 10460

I have a class A, that looks like the following:

public class A {

  // there is a public API that uses both
  // method1 and method2, but that's not important
  // in this question.
  public Integer publicApi(Integer a, Integer b) {
    // a bunch of other stuff is done that is 
    // not related to method1 or method2 here.
    // However, method1 IS used somewhere in here.
    // For now, I don't want to test other
    // implementation details for this API, I only
    // am interested in testing method1.

    return method1(a, b);
  }

  private static Integer method1(Integer a, Integer b) {
    if(method2(a, b, 10) == null) {
      return -1;
    }
    return 10 + method2(a, b, 10);
  }

  private static Integer method2(Integer a, Integer b, Integer c) {
    // some complicated logic with multiple values 
    // to return (based on various conditions).

    // however, I want to simply test what happens
    // when this method returns null (which is a possibility).
    return a+b+c;
  }
}

As is given, my class A has a public API that's (sort of) complicated logic, that I don't want to test (for the purpose of this question). Say I am only interested in testing method1.

Here is my test code (I'm using PowerMockito):

import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import java.lang.reflect.Method;
import static org.junit.Assert.assertNull;
import static org.powermock.api.mockito.PowerMockito.spy;
import static org.powermock.api.mockito.PowerMockito.when;
import static org.powermock.api.support.membermodification.MemberMatcher.method;

@RunWith(PowerMockRunner.class)
@PrepareForTest(A.class)
public class SimpleTest {

  @Test
  public void testMethod1Invocation() throws Exception {

    spy(A.class);

    when(A.class, method(A.class,
        "method2", Integer.class,
        Integer.class, Integer.class))
        .withArguments(1, 2, 10)
        .thenReturn(null);

    // use reflection to call method1
    Method method1 = A.class.getDeclaredMethod(
        "method1",
        Integer.class, Integer.class
    );

    method1.setAccessible(true);
    Object ret = method1.invoke(1, 2);
    assertEquals(-1, ret);
  }
}

But, I get the following error:

com.apple.geo.tart.A.method1(java.lang.Integer, java.lang.Integer, java.lang.Integer)
java.lang.NoSuchMethodException: com.apple.geo.tart.A.method1(java.lang.Integer, java.lang.Integer, java.lang.Integer)
    at java.lang.Class.getDeclaredMethod(Class.java:2130)
    at com.apple.geo.tart.SimpleTest.testMethod1Invocation(SimpleTest.java:32)

I don't see what I'm doing wrong here. As it seems to me, there are 3 things that I need here:

  1. Spy on A so that I can mock when/thenReturn on the static methods.
  2. Mock the private static method that I'm interested in (method2 in this case).
  3. Use reflection to access method1, and then invoke it.

How do I then mock a private static method (method2), just so that I can test another private static method(method1) of the same class that depends on the first?

1 Answers
Related