mockito: Mock enum with methods fails on Java 17
The following fails on Java 17 and works on 11 and 16:
public enum ExampleEnum {
TEST {
public String retrieve() {
return "test";
}
};
public String getValue() {
return "21";
}
}
public class Container {
private ExampleEnum exampleEnum;
public Container(ExampleEnum exampleEnum) {
this.exampleEnum = exampleEnum;
}
public String retrieveValue() {
return exampleEnum.getValue();
}
}
@ExtendWith(MockitoExtension.class)
public class ExampleEnumTest {
@Mock
private ExampleEnum exampleEnum;
@Test
public void testEnumWithMethods() {
Container container = new Container(exampleEnum);
Mockito.when(exampleEnum.getValue()).thenReturn("42");
assertEquals("42", container.retrieveValue());
}
}
On 17 it gives the following error:
org.mockito.exceptions.base.MockitoException:
Mockito cannot mock this class: class com.example.ExampleEnum.
If you're not sure why you're getting this error, please report to the mailing list.
Java : 17
JVM vendor name : Oracle Corporation
JVM vendor version : 17-ea+24-2164
JVM name : OpenJDK 64-Bit Server VM
JVM version : 17-ea+24-2164
JVM info : mixed mode, sharing
OS name : Linux
OS version : 4.19.76-linuxkit
You are seeing this disclaimer because Mockito is configured to create inlined mocks.
You can learn about inline mocks and their limitations under item #39 of the Mockito class javadoc.
Underlying exception : org.mockito.exceptions.base.MockitoException: Could not modify all classes [interface java.lang.constant.Constable, class java.lang.Object, interface java.lang.Comparable, interface java.io.Serializable, class java.lang.Enum, class com.example.ExampleEnum]
Caused by: org.mockito.exceptions.base.MockitoException: Could not modify all classes [interface java.lang.constant.Constable, class java.lang.Object, interface java.lang.Comparable, interface java.io.Serializable, class java.lang.Enum, class com.example.ExampleEnum]
Caused by: java.lang.UnsupportedOperationException: class redefinition failed: attempted to change the class NestHost, NestMembers, Record, or PermittedSubclasses attribute
The complete code example can be found here: https://github.com/johanjanssen/JavaUpgrades/tree/main/java17
It can be build with Docker for instance with (17 can be replaced with 11 and 16): docker build -t javaupgrades -f …\Dockerfile --build-arg JDK_VERSION=17 .
Is there some way I can work around this issue?
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 1
- Comments: 29 (12 by maintainers)
The approach here is to change your program so you don’t have to mock enums.
Say your enum is called Color and it’s got members MAUVE, BEIGE and AMBER, and you want to mock a new color for testing. You can’t, though, because enums are closed sets. To fix this:
On Wed, Nov 9, 2022, 6:02 PM Namdi @.***> wrote:
Mocking enums is probably a dubious practice. If the enum represents a closed set, you shouldn’t be adding a new member at test time.
If you’re using an enum as a convenient way to hold a set of singletons, then add an interface which the enum can implement and mock that, instead.
Peter
On Mon, Nov 7, 2022, 6:56 PM jonatanloya @.***> wrote:
Fixed it on master, it’s a documentation error in ASM so I don’t have to wait for a release. I have some other minor issues I have to address but it will be fixed eventually.