mardi 24 novembre 2015

Using Power Mock to create spies / partial mocks on all new Instances of a Inner Class

I have an non-static inner class in java. Which I wish to replace with spies in a unit test using Power Mock (Power Mock is being run as a rule in Robolectric).

public class OuterClass {
     class InnerClass {
          InnerClass(int timestamp, String uuId) {  // package private constructor.
          }
     }
}

The header of the test of the OuterClass looks like the following :

@RunWith(RobolectricGradleTestRunner.class)
@Config(sdk = 21, constants = BuildConfig.class)
@PowerMockIgnore({
    "org.mockito.*"
    , "org.robolectric.*"
    , "android.*"
})
@PrepareForTest({
    OuterClass.class
    , OuterClass.InnerClass.class
})
public class OuterClassTest {

I'm have tried to following ways to replace all track all new instances of the inner class but I haven't managed to get any of them to work.

    whenNew(OuterClass.InnerClass.class).withAnyArguments().thenAnswer(new Answer<OuterClass.InnerClass>() {
        @Override
        public OuterClass.InnerClass answer(InvocationOnMock invocation) throws Throwable {
            OuterClass.InnerClass spy = spy((OuterClass.InnerClass) invocation.getArguments()[0]);
            mListOfAllInnerClassSpies.add(spy);
            return spy;
        }
    });

I when I run this no InnerClasses seem to be created, or no methods on the InnerClass seem to be run.

    OuterClass outerClass = spy(new OuterClass());  
    List<OuterClass.InnerClass> innerClassSpies = new ArrayList<OuterClass.InnerClass>();
    ArgumentCaptor<Integer> timestamp = ArgumentCaptor.forClass(Integer.class);
    ArgumentCaptor<String> uuid = ArgumentCaptor.forClass(String.class);

    whenNew(OuterClass.InnerClass.class)
    .withParameterTypes(
                    OuterClass.class
                    , Integer.class
                    , String.class
            )
    .withArguments(
           outerClass
           , timestamp.capture()
            , uuid.capture()
    )
    .thenAnswer(
            new Answer<OuterClass.InnerClass>() {
                @Override
                public OuterClass.InnerClass answer(InvocationOnMock invocation) throws Throwable {
                    OuterClass.InnerClass spy = spy(outerClass.new InnerClass(timestamp.getValue(), uuid.getValue()));
                    innerClassSpies.add(spy);
                    return spy;
                }
    });

When I run the above code I get the following exception :

org.powermock.reflect.exceptions.ConstructorNotFoundException: Failed to lookup constructor with parameter types [ OuterClass, java.lang.Integer, java.lang.String ] in class OuterClass$InnerClass.

Any solution which can "track" all Inner Classes created by the Outer Class would be great, preferably using the mockito paradigm.

Aucun commentaire:

Enregistrer un commentaire