jeudi 20 août 2015

Mock new instance created through reflection using PowerMockito

I've got a class called ConfigReferenceProcessor that is responsible for instantiating new objects of a given type and configuring them using the provided configuration information. The type of the object that is instantiated must derive from an abstract base class called BaseConfigurable (There are methods defined in this base class that I need to call in order to configure the new instance). A note going forward: BaseConfigurable is out of my control, so I can't make any changes to its code.

I'm trying to unit test the method processConfigReference, which does the following:

public <T extends BaseConfigurable> T processConfigReference(
        Class<T> clazz, ConfigReferenceCfg configRef) {
    // Reflection magic to created a new instance ending with:
    T obj = constructor.newInstance();

    // Some methods to setup and configure the new instance, including:
    obj.loadConfig(configRef.getConfigName());

    return obj;
}

In my unit test, I need control over the loadConfig method because I don't want to drag in the entire configuration behaviour with file system lookups, etc. My first thought was to simply create my own mock object:

static class MockConfigurable extends BaseConfigurable {

    @Override
    public void loadConfig(String configName) {
        // Do nothing.
    }

    // Mandatory methods
}

Unfortunately, I can't override loadConfig because it's declared as final in the base class.

I found other questions on stack overflow about mocking object creation using the PowerMockito method whenNew and tried using that to set up my mock by mocking the final method and also returning the mock object when new instances are created:

@RunWith(PowerMockRunner.class)
@PrepareForTest({ TestConfigReferenceProcessor.MockConfigurable.class, ConfigReferenceProcessor.class })
public class TestConfigReferenceProcessor {
    static class MockConfigurable extends BaseConfigurable {
        // Mandatory methods
    }

    @Mock private MockConfigurable mockConfigurable;

    @Before
    public void initializeMockConfigurableInstance() throws Exception {
        doNothing().when(mockConfigurable).loadConfig(any(String.class));
        whenNew(MockConfigurable.class).withAnyArguments().thenReturn(mockConfigurable);
    }

    @Test
    public void shouldProcessConfigRef() {
        MockConfigurable result = 
                ConfigReferenceProcessor.forClass(MockConfigurable.class)
                                        .processConfigReference(configRefCfg);

        // Fails!
        verify(mockConfigurable).loadConfig(any(String.class));
    }
}

But this approach doesn't seem to work for me. I suspect it doesn't work because I'm not actually creating an object using new.

Is there any other way to get around this problem?





Aucun commentaire:

Enregistrer un commentaire