1

I would like to mock isPrivate(int flags) method from java.lang.reflect.Modifier with Mockito.

Tried:

try(MockedStatic<Modifier> modifier = Mockito.mockStatic(Modifier.class)){
    modifier.when(() -> Modifier.isPrivate(anyInt()).thenReturn(true);
    //assertions
}

but I get such error:

java.lang.IllegalAccessError:symbolic reference class is not accessible: class java.lang.invoke.LambdaMetafactory

I have always been mocking static methods like that and I do not understand why it doesnt work in this particular scenario. How can I mock this method?

zaoras
  • 51
  • 5

1 Answers1

1

As suggested by Mockito.mockStatic

Note: We recommend against mocking static methods of classes in the standard library or classes used by custom class loaders used to executed the block with the mocked class...

This is an interesting example demonstrate why we should not mock static method in standard library, especially core class like Modifier.

Keep in mind that public static method is GLOBAL by nature.

mocking them is quite similar to modifying global variable.

The problem is when you apply mockStatic on Modifier, all method are mocked, including isPublic, which will return false by default.

Hence when executing lambda and checking access, IllegalAccessError is thrown.

For details, check below source.

  1. MethodHandleNatives.java#L615
  2. MethodHandles.java#L4135
  3. MethodHandles.java#L3685
  4. MethodHandles.java#L3697
  5. VerifyAccess.java#L199

Which finally call

        if (isPublic(mods)) {

            Module lookupModule = lookupClass.getModule();
            Module refModule = refc.getModule();
            ...

Solution

There is no simple way to tweak the static mock to solve the problem. I suggest following answer of Mocking static methods with Mockito, which create a wrapper to wrap Modifier static method. Then you can mock the wrapper method without affecting other caller.

samabcde
  • 6,988
  • 2
  • 25
  • 41