Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Static-mocking java.util.Locale results in a stack overflow #3197

Closed
doublep opened this issue Dec 12, 2023 · 2 comments
Closed

Static-mocking java.util.Locale results in a stack overflow #3197

doublep opened this issue Dec 12, 2023 · 2 comments

Comments

@doublep
Copy link

doublep commented Dec 12, 2023

Mockito 5.8.0, Java 17.0.8. Simply executing this line:

org.mockito.Mockito.mockStatic (java.util.Locale.class);

results in a StackOverflowError:

Exception in thread "main" java.lang.StackOverflowError
        at java.base/java.util.concurrent.ConcurrentHashMap.putVal(ConcurrentHashMap.java:1012)
        at java.base/java.util.concurrent.ConcurrentHashMap.putIfAbsent(ConcurrentHashMap.java:1541)
        at java.base/java.lang.ClassLoader.getClassLoadingLock(ClassLoader.java:671)
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:651)
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:700)
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:676)
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:639)
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525)
        at org.mockito.internal.creation.bytebuddy.MockMethodAdvice.handleStatic(MockMethodAdvice.java:145)
        at java.base/java.util.Locale.getDefault(Locale.java:924)
        at java.base/java.lang.String.toLowerCase(String.java:3417)
        at java.base/sun.net.util.URLUtil.urlNoFragString(URLUtil.java:53)
        at java.base/java.security.CodeSource.<init>(CodeSource.java:123)
        at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:861)
        at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:760)
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:681)
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:639)
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525)
        at org.mockito.internal.creation.bytebuddy.MockMethodAdvice.handleStatic(MockMethodAdvice.java:145)
        at java.base/java.util.Locale.getDefault(Locale.java:924)
        at java.base/java.lang.String.toLowerCase(String.java:3417)
        [...]

In comparison, when trying to mock Thread or System, Mockito at least gives you a nice exception, not fails somewhere internally. FWIW, it is fine for me if mocking Locale is also not supported, but there should at least be a nice message.

Usecase: was trying to test with different results of Locale.getDefault (...) by mocking that. In the end reverted to using Locale.setDefault (...), but that's a bit ugly as that's not thread-safe (hardly matters in testing code, but still) and you need to restore original value.

@TimvdLippe
Copy link
Contributor

Unfortunately, java.util.Locale is one of the classes that Mockito relies on internally for its behavior. Stubbing java.util.Locale will therefore lead to undefined behavior. Additionally, it is advised not to mock classes you don't own: https://github.com/mockito/mockito/wiki/How-to-write-good-tests#dont-mock-a-type-you-dont-own We are working on improving the user experience by working on a DoNotMock feature to avoid mocking classes/methods that are known to crash Mockito internals (#1833). Therefore, I am closing this as "Infeasible". Apologies for the uninformative exception that is thrown.

@doublep
Copy link
Author

doublep commented Dec 12, 2023

Apologies for the uninformative exception that is thrown.

Yeah, not like you could do something about it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants