Skip to content

Commit

Permalink
Mockito fails with JVM internal error when mocking class where clinit…
Browse files Browse the repository at this point in the history
… does not find a transitive dependency

Mockito now throws Errors occurred during class initialization to callers
instead of swallowing it, and the JVM reporting an obscure exception.

Fixes #3498
  • Loading branch information
AndreasTu committed Nov 6, 2024
1 parent 582e3fa commit fcd0f73
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -234,12 +234,16 @@ public synchronized void mockClassConstruction(Class<?> type) {
private static void assureInitialization(Class<?> type) {
try {
Class.forName(type.getName(), true, type.getClassLoader());
} catch (ExceptionInInitializerError e) {
} catch (Error error) {
Throwable ex = error;
if (ex instanceof ExceptionInInitializerError) {
ex = ((ExceptionInInitializerError) ex).getException();
}
throw new MockitoException(
"Cannot instrument "
+ type
+ " because it or one of its supertypes could not be initialized",
e.getException());
ex);
} catch (Throwable ignored) {
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2024 Mockito contributors
* This program is made available under the terms of the MIT License.
*/
package org.mockitousage.bugs.creation;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;

import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.exceptions.base.MockitoException;

// See Issue #3498
public class MockClassWithMissingStaticDepTest {

@Test
public void shouldNotSwallowCinitErrorsOfClassToMock() {
try {
@SuppressWarnings("unused")
var unused = Mockito.mock(ClassWithErrorInClassInit.class);

fail();
} catch (MockitoException e) {
var cause = e.getCause();
assertThat(cause).isInstanceOf(MockitoException.class);
assertThat(cause.getMessage())
.isEqualTo(
"Cannot instrument class org.mockitousage.bugs.creation.MockClassWithMissingStaticDepTest$ClassWithErrorInClassInit because it or one of its supertypes could not be initialized");

var cause2 = cause.getCause();
assertThat(cause2).isInstanceOf(NoClassDefFoundError.class);
assertThat(cause2.getMessage())
.isEqualTo("Simulate missing transitive dependency used in class init.");
}
}

private static class ClassWithErrorInClassInit {
static {
//noinspection ConstantValue
if (true) {
throw new NoClassDefFoundError(
"Simulate missing transitive dependency used in class init.");
}
}
}
}

0 comments on commit fcd0f73

Please sign in to comment.