Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocking static class

I have a method in a class that instantiate a static class instance and call operation on it.

public class SomeClass {
    public void someMethod() {
       MyClass.MyStaticClass myStaticClassInstance =
          new MyClass.MyStaticClass( arg1, arg2, arg3 );
       myStaticClassInstance.callSomeMethod();
    }
}

public class MyClass {

   public static class MyStaticClass {

      public MyStaticClass( Object arg1, Object arg2, Object arg3 ) {
      }

      public void callSomeMethod() {
      }
   }
}

How to mock static class instanciation, so that I could mock callSomeMethod() without going through the static class constructor ?

like image 906
jerome Avatar asked Oct 30 '22 13:10

jerome


1 Answers

You can do it with PowerMock by mocking instantiation of your static inner class. This can be done by preparing the class that will actually instantiate your static inner class so here it will be the class in which you have the method someMethod() defined.

Assuming that someMethod() is defined into the class MyOtherClass and returns nothing, your test class would be something like this:

@RunWith(PowerMockRunner.class) // The runner of PowerMock
@PrepareForTest(MyOtherClass.class) // the class to prepare
public class MyClassTest {

    @Test
    public void test() throws Exception {
        // The mock of your static inner class to return
        MyClass.MyStaticClass mock = Mockito.mock(MyClass.MyStaticClass.class);
        // Mock the call of callSomeMethod()
        PowerMockito.doAnswer(
            new Answer<Void>() {
                @Override
                public Void answer(final InvocationOnMock invocation) throws Throwable {
                    // Do something here as new implementation of callSomeMethod
                    System.out.println("My new Answer");
                    return null;
                }
            }
        ).when(mock).callSomeMethod();
        // Return your mock in case we instantiate MyClass.MyStaticClass in 
        // the prepared class with any arguments  
        PowerMockito.whenNew(MyClass.MyStaticClass.class)
            .withArguments(Matchers.any(), Matchers.any(), Matchers.any())
            .thenReturn(mock);

        // The code that will call someMethod
        MyOtherClass mc = new MyOtherClass();
        mc.someMethod();
    }
}

Assuming that my class MyClass looks like this:

public class MyClass {

    public static class MyStaticClass {
        public MyStaticClass(Object arg1, Object arg2, Object arg3) {
            System.out.println("Called constructor");
        }

        public void callSomeMethod() {
            System.out.println("callSomeMethod");
        }
    }
}

And my class MyOtherClass looks like this:

public class MyOtherClass {
    public void someMethod() {
        MyClass.MyStaticClass myStaticClassInstance = new MyClass.MyStaticClass(
            new Object(), new Object(), new Object()
        );
        myStaticClassInstance.callSomeMethod();
    }
}

If I launch my test, I get as expected:

My new Answer

Instead of what I should get by default:

Called constructor
callSomeMethod

More details about how to constructions of new objects.

like image 164
Nicolas Filotto Avatar answered Nov 09 '22 12:11

Nicolas Filotto