OutputCaptureExtension doesn't work in native image tests, as seen here.
It fails with:
JUnit Jupiter:OutputCaptureTests
ClassSource [className = 'com.example.commandlinerunner.OutputCaptureTests', filePosition = null]
=> java.lang.NoSuchMethodException: org.springframework.boot.test.system.OutputCapture.<init>()
java.base@17.0.5/java.lang.Class.getConstructor0(DynamicHub.java:3585)
java.base@17.0.5/java.lang.Class.getDeclaredConstructor(DynamicHub.java:2754)
org.junit.platform.commons.util.ReflectionUtils.newInstance(ReflectionUtils.java:527)
org.junit.platform.commons.support.ReflectionSupport.newInstance(ReflectionSupport.java:181)
org.junit.jupiter.api.extension.ExtensionContext$Store.lambda$getOrComputeIfAbsent$0(ExtensionContext.java:528)
[...]
Suppressed: java.lang.NoSuchMethodException: org.springframework.boot.test.system.OutputCapture.<init>()
java.base@17.0.5/java.lang.Class.getConstructor0(DynamicHub.java:3585)
java.base@17.0.5/java.lang.Class.getDeclaredConstructor(DynamicHub.java:2754)
org.junit.platform.commons.util.ReflectionUtils.newInstance(ReflectionUtils.java:527)
org.junit.platform.commons.support.ReflectionSupport.newInstance(ReflectionSupport.java:181)
org.junit.jupiter.api.extension.ExtensionContext$Store.lambda$getOrComputeIfAbsent$0(ExtensionContext.java:528)
[...]
Suppressed: java.lang.NoSuchMethodException: org.springframework.boot.test.system.OutputCapture.<init>()
java.base@17.0.5/java.lang.Class.getConstructor0(DynamicHub.java:3585)
java.base@17.0.5/java.lang.Class.getDeclaredConstructor(DynamicHub.java:2754)
org.junit.platform.commons.util.ReflectionUtils.newInstance(ReflectionUtils.java:527)
org.junit.platform.commons.support.ReflectionSupport.newInstance(ReflectionSupport.java:181)
org.junit.jupiter.api.extension.ExtensionContext$Store.lambda$getOrComputeIfAbsent$0(ExtensionContext.java:528)
[...]
Comment From: mhalbritter
It runs with a config like this:
[
{
"condition": {
"typeReachable": "org.springframework.boot.test.system.OutputCaptureExtension"
},
"name": "org.springframework.boot.test.system.OutputCapture",
"methods": [
{
"name": "<init>",
"parameterTypes": [
]
}
]
}
]
The thing is, this @ExtendWith(OutputCaptureExtension.class) can be used without any involvement of Spring (Boot) in JUnit 5 at all, so we can't hook a RuntimeHintsRegistrar in it. We can either write this config when running processTestAot or put it as a file in META-INF/native-image/org.springframework.boot/spring-boot-test.
Comment From: mhalbritter
There's a org.springframework.test.context.aot.TestRuntimeHintsRegistrar interface which can be hooked into, which generates runtime hints for tests. Going to use this.
Comment From: wilkinsona
I don't think we need to use hints for this. Instead, I think it will work if we change getOutputCapture to the following:
private OutputCapture getOutputCapture(ExtensionContext context) {
return getStore(context).getOrComputeIfAbsent(OutputCapture.class, (key) -> new OutputCapture(), OutputCapture.class);
}
Comment From: mhalbritter
Ah, saw your comment too late. You're right, let's eliminate reflection altogether.