diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassTemplateInvocationTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassTemplateInvocationTestDescriptor.java index 9d3037b6059b..afa3e639daac 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassTemplateInvocationTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassTemplateInvocationTestDescriptor.java @@ -10,6 +10,7 @@ package org.junit.jupiter.engine.descriptor; +import static java.util.Collections.emptySet; import static java.util.Objects.requireNonNull; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.jupiter.engine.descriptor.CallbackSupport.invokeAfterCallbacks; @@ -36,6 +37,7 @@ import org.junit.jupiter.engine.extension.MutableExtensionRegistry; import org.junit.platform.engine.TestSource; import org.junit.platform.engine.UniqueId; +import org.junit.platform.engine.support.hierarchical.ExclusiveResource; import org.junit.platform.engine.support.hierarchical.ThrowableCollector; /** @@ -112,6 +114,12 @@ public Function> getResou // --- Node ---------------------------------------------------------------- + @Override + public Set getExclusiveResources() { + // Resources are already collected and returned by the enclosing ClassTemplateTestDescriptor + return emptySet(); + } + @Override public JupiterEngineExecutionContext prepare(JupiterEngineExecutionContext context) { MutableExtensionRegistry registry = context.getExtensionRegistry(); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/ClassTemplateInvocationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/ClassTemplateInvocationTests.java index 8be2bab63816..50c6e8ab3d6c 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/ClassTemplateInvocationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/ClassTemplateInvocationTests.java @@ -79,6 +79,7 @@ import org.junit.jupiter.api.extension.ParameterResolutionException; import org.junit.jupiter.api.extension.ParameterResolver; import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.api.parallel.ResourceLock; import org.junit.jupiter.engine.descriptor.ClassTemplateInvocationTestDescriptor; import org.junit.jupiter.engine.descriptor.ClassTemplateTestDescriptor; import org.junit.jupiter.engine.descriptor.ClassTestDescriptor; @@ -1004,6 +1005,14 @@ void ignoresComposedAnnotations() { assertThat(engineDescriptor.getDescendants()).isEmpty(); } + @Test + void classTemplateWithResourceLockExecutesSuccessfully() { + var results = executeTestsForClass(ClassTemplateWithResourceLockTestCase.class); + + results.testEvents().assertStatistics(stats -> stats.started(2).succeeded(2)); + results.containerEvents().assertStatistics(stats -> stats.started(4).succeeded(4)); + } + // ------------------------------------------------------------------- private static Stream allReportEntryValues(EngineExecutionResults results) { @@ -1567,4 +1576,15 @@ void test() { } } + @SuppressWarnings("JUnitMalformedDeclaration") + @ClassTemplate + @ExtendWith(TwoInvocationsClassTemplateInvocationContextProvider.class) + @ResourceLock("test-resource") + static class ClassTemplateWithResourceLockTestCase { + @Test + void test() { + // This test verifies that @ResourceLock works with @ClassTemplate (issue #5155) + } + } + }