Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ignoring invoking internal static call

public static ResponseBean call(Bean bean) throws Exception {
    // statements...
    IgnoreCall.ignoreMethodCall(bean);
    // statements...

    // return
}

With the code snippet above, is it possible to test the method ignoring invocation of IgnoreCall.ignoreMethod(Bean) without needing to place the entire statement under a boolean condition?

Here's the unit test code snippet:

@RunWith(PowerMockRunner.class)
@PrepareTest
public ClassHelperTest {

    @Test
    public void testCall() throws Excpetion {
        // stubbing...
        ResponseBean responseBean = ClassHelper.call(bean);
        // verify/ies
        // assert/s
    }

}

Notes:

  • Refactoring ClassHelper.call(Bean) should be avoided. Even with a bad OO design, refactoring is costly.
  • Method signature is locked unless another pattern is applicable for replacement.
  • Tried using Mockito.when and PowerMockito.when on the target static method, stubbing didn't work on run-time debug.
like image 702
David B Avatar asked Mar 11 '23 11:03

David B


1 Answers

As your comments indicate that changing your production code is not possible, you "simply" have to dive into the static-mocking aspects of PowerMock; as outlined here for example.

Basically you need to enable IgnoreCall for static mocking; and then you make calls to ignoreMethodCall() a no-op.

But as you keep asking: the core problem with your question is the fact that you want to mock out a static method that is void. I have a complete example below, but before that some explanations.

The point is: you call a method for two reasons:

  1. It has a side effect
  2. It returns a value, and maybe, causes a side effect, too

A void method can only be called for side effects. And the thing is: when you do static mocking, then that works on class level.

Meaning: you instruct PowerMock to "prevent" any of the static methods of some class from execution; you simply "erase" the side effects of all those static methods! So, by telling PowerMock to do those static mocks, all void methods are already "gone".

But as said, you might also call methods for their return value. And then is when the when() method of Mockito kicks in. You use that method to say: when that value-returning method is invoked, then do this or that.

Long story short; here is a [mcve] using the elements you asked for:

package ghostcat.test;

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

class IgnoreCall {
  public static void ignoreMethodCall(Object o) {
    System.out.println("SHOULD NOT SHOW UP: " + o);
  }
}

class CuT {
  public static Object call(Object bean) {
    System.out.println("statement1");
    IgnoreCall.ignoreMethodCall(bean);
    System.out.println("statement2");
    return "whatever";
  }
}

@RunWith(PowerMockRunner.class)
@PrepareForTest(IgnoreCall.class)
public class PMTest {
  @Test
  public void test() {
    PowerMockito.mockStatic(IgnoreCall.class);
    CuT.call("yeha");
  }
}

As in your example ... there is IgnoreCall; used within that a static method that I just called "call".

This prints:

statement1
statement2

When I go in and comment out

//      PowerMockito.mockStatic(IgnoreCall.class);

It prints:

statement1
SHOULD NOT SHOW UP: yeha
statement2

So, a simple example that should tell you exactly what you need to do.

I worked with eclipse neon, IBM java8 JDK, and simply imported all the JARs from powermock-mockito-junit-1.6.6.zip into my test project.

like image 64
GhostCat Avatar answered Mar 27 '23 15:03

GhostCat