Interesting Mockito / reflection feature & workaround

So, you have two interfaces:

interface SettingsProvider {
  Settings getSettings(String id);
}

and

interface InternalSettingsProvider extends SettingsProvider {
  @Override
  InternalSettings getSettings(String id);
}

You mock one of the second, and you stub the method:

InternalSettingsProvider mockProvider =
    mock(InternalSettingsProvider.class);
when(mockProvider.getSettings(“anId”)).thenReturn(someSettings);

You run some code that only knows about SettingsProvider, not InternalSettingsProvider. This code calls getSettings(“anId”). You’re expecting it to then make use of someSettings so…

…you get a NullPointerException.

It turns out that, with reflection, it actually makes a difference whether you call getSettings() on SettingsProvider or on InternalSettingsProvider. Each interface results in a separate Method object.

When the SettingsProvider#getSettings() call comes in, the matching code looks at the Methods it has registered for stubbing, and it finds one for InternalSettingsProvider#getSettings(), but none for SettingsProvider#getSettings(). So it returns the default value, which for an object is null.

Luckily, the first workaround you might think of does actually do the trick.

when(((SettingsProvider) mockProvider)
    .getSettings(“anId”)).thenReturn(someSettings);

I ran into this with Mockito, but I imagine it’ll come up in some other reflection-related contexts too.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s