This is an automated email from the ASF dual-hosted git repository. benw pushed a commit to branch gradle-improvements-javax in repository https://gitbox.apache.org/repos/asf/tapestry-5.git
commit b474b2110750f0bffdfbbad7615215c07efa4f28 Author: Ben Weidig <[email protected]> AuthorDate: Sat Sep 13 13:23:58 2025 +0200 TAP5-2809: fix tapestry-ioc-junit compilation issues --- .../ioc/junit/TapestryIOCJUnit4ClassRunner.java | 150 -------------- .../ioc/junit/TapestryIOCJUnitExtension.java | 108 ++++++++++ .../tapestry5/ioc/junit/TestRegistryManager.java | 226 +++++++++++---------- 3 files changed, 231 insertions(+), 253 deletions(-) diff --git a/tapestry-ioc-junit/src/main/java/org/apache/tapestry5/ioc/junit/TapestryIOCJUnit4ClassRunner.java b/tapestry-ioc-junit/src/main/java/org/apache/tapestry5/ioc/junit/TapestryIOCJUnit4ClassRunner.java deleted file mode 100644 index d12741978..000000000 --- a/tapestry-ioc-junit/src/main/java/org/apache/tapestry5/ioc/junit/TapestryIOCJUnit4ClassRunner.java +++ /dev/null @@ -1,150 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package org.apache.tapestry5.ioc.junit; - -import org.apache.tapestry5.ioc.annotations.Inject; -import org.apache.tapestry5.ioc.def.ModuleDef; -import org.junit.runner.Description; -import org.junit.runner.Result; -import org.junit.runner.notification.Failure; -import org.junit.runner.notification.RunListener; -import org.junit.runner.notification.RunNotifier; -import org.junit.runner.notification.StoppedByUserException; -import org.junit.runners.BlockJUnit4ClassRunner; -import org.junit.runners.model.InitializationError; -import org.junit.runners.model.Statement; - -/** - * - * A JUnit4ClassRunner to help with Tapestry IOC integration tests. The test - * runner requires a registry configuration to be defined in a {@link Registry} - * annotation. A {@link RegistryShutdownType} can be specified to configure the - * lifecycle of the test registry and it's services - * - * - * - * {@link org.apache.tapestry5.ioc.junit.ModuleDef}s can be added to the - * {@link org.apache.tapestry5.ioc.Registry} by annotating a factory method(s) - * with {@link ModuleDef}. These {@link ModuleDef} factory methods must be - * <ul> - * <li>public</li> - * <li>static</li> - * <li>take zero arguments</li> - * <li>return a subclass of {@link org.apache.tapestry5.ioc.junit.ModuleDef}</li> - * </ul> - * - * - * - * Any services defined in the registry can be {@link Inject}ed into the test - * class to be used during testing. - * - */ -public class TapestryIOCJUnit4ClassRunner extends BlockJUnit4ClassRunner { - private final TestRegistryManager registryManager; - - public TapestryIOCJUnit4ClassRunner(Class<?> type) throws InitializationError { - super(type); - this.registryManager = new TestRegistryManager(type); - } - - @Override - public void run(RunNotifier notifier) { - RunNotifier wrapper = new RegistryManagerRunNotifier(registryManager, notifier); - super.run(wrapper); - } - - @Override - protected Statement withAfterClasses(Statement statement) { - final Statement superStatement = super.withAfterClasses(statement); - return new Statement() { - @Override - public void evaluate() throws Throwable { - superStatement.evaluate(); - registryManager.afterTestClass(); - } - }; - } - - @Override - protected Object createTest() throws Exception { - org.apache.tapestry5.ioc.Registry registry = registryManager.getOrCreateRegistry(); - return registry.autobuild(getTestClass().getJavaClass()); - } - - public static class RegistryManagerRunNotifier extends RunNotifier { - private final RunNotifier delegate; - private final TestRegistryManager registryManager; - - public RegistryManagerRunNotifier(TestRegistryManager registryManager, RunNotifier delegate) { - super(); - this.delegate = delegate; - this.registryManager = registryManager; - } - - @Override - public void addListener(RunListener listener) { - delegate.addListener(listener); - } - - @Override - public void removeListener(RunListener listener) { - delegate.removeListener(listener); - } - - @Override - public void fireTestRunStarted(Description description) { - delegate.fireTestRunStarted(description); - } - - @Override - public void fireTestRunFinished(Result result) { - delegate.fireTestRunFinished(result); - } - - @Override - public void fireTestStarted(Description description) throws StoppedByUserException { - delegate.fireTestStarted(description); - } - - @Override - public void fireTestFailure(Failure failure) { - delegate.fireTestFailure(failure); - } - - @Override - public void fireTestAssumptionFailed(Failure failure) { - delegate.fireTestAssumptionFailed(failure); - } - - @Override - public void fireTestIgnored(Description description) { - delegate.fireTestIgnored(description); - } - - @Override - public void fireTestFinished(Description description) { - registryManager.afterTestMethod(); - delegate.fireTestFinished(description); - } - - @Override - public void pleaseStop() { - delegate.pleaseStop(); - } - - @Override - public void addFirstListener(RunListener listener) { - delegate.addFirstListener(listener); - } - } -} \ No newline at end of file diff --git a/tapestry-ioc-junit/src/main/java/org/apache/tapestry5/ioc/junit/TapestryIOCJUnitExtension.java b/tapestry-ioc-junit/src/main/java/org/apache/tapestry5/ioc/junit/TapestryIOCJUnitExtension.java new file mode 100644 index 000000000..f6e75087d --- /dev/null +++ b/tapestry-ioc-junit/src/main/java/org/apache/tapestry5/ioc/junit/TapestryIOCJUnitExtension.java @@ -0,0 +1,108 @@ +// Copyright 2025 The Apache Software Foundation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package org.apache.tapestry5.ioc.junit; + +import java.lang.reflect.Field; + +import org.apache.tapestry5.ioc.Registry; +import org.apache.tapestry5.ioc.annotations.Inject; +import org.junit.jupiter.api.extension.AfterAllCallback; +import org.junit.jupiter.api.extension.AfterEachCallback; +import org.junit.jupiter.api.extension.BeforeAllCallback; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.TestInstanceFactory; +import org.junit.jupiter.api.extension.TestInstanceFactoryContext; +import org.junit.jupiter.api.extension.TestInstantiationException; + +public class TapestryIOCJUnitExtension implements BeforeAllCallback, AfterAllCallback, + BeforeEachCallback, AfterEachCallback, TestInstanceFactory +{ + + private TestRegistryManager registryManager; + + @Override + public void beforeAll(ExtensionContext context) throws Exception + { + Class<?> testClass = context.getRequiredTestClass(); + registryManager = new TestRegistryManager(testClass); + } + + @Override + public void afterAll(ExtensionContext context) throws Exception + { + if (registryManager != null) + { + registryManager.afterTestClass(); + } + } + + @Override + public void beforeEach(ExtensionContext context) throws Exception + { + // No-op: lifecycle handled by createTestInstance + } + + @Override + public void afterEach(ExtensionContext context) throws Exception + { + if (registryManager != null) + { + registryManager.afterTestMethod(); + } + } + + @Override + public Object createTestInstance(TestInstanceFactoryContext factoryContext, + ExtensionContext extensionContext) throws TestInstantiationException + { + if (registryManager == null) + { + registryManager = new TestRegistryManager(factoryContext.getTestClass()); + } + try + { + Registry registry = registryManager.getOrCreateRegistry(); + Object testInstance = registry.autobuild(factoryContext.getTestClass()); + injectFields(testInstance, registry); + return testInstance; + } + catch (Exception e) + { + throw new TestInstantiationException("", e); + } + } + + private void injectFields(Object instance, Registry registry) + { + Class<?> clazz = instance.getClass(); + for (Field field : clazz.getDeclaredFields()) + { + if (field.isAnnotationPresent(Inject.class)) + { + Object service = registry.getObject(field.getType(), null); + field.setAccessible(true); + try + { + field.set(instance, service); + } + catch (IllegalAccessException e) + { + throw new RuntimeException("Failed to inject field: " + field, e); + } + } + } + } +} diff --git a/tapestry-ioc-junit/src/main/java/org/apache/tapestry5/ioc/junit/TestRegistryManager.java b/tapestry-ioc-junit/src/main/java/org/apache/tapestry5/ioc/junit/TestRegistryManager.java index fd8ac454f..d74b61519 100644 --- a/tapestry-ioc-junit/src/main/java/org/apache/tapestry5/ioc/junit/TestRegistryManager.java +++ b/tapestry-ioc-junit/src/main/java/org/apache/tapestry5/ioc/junit/TestRegistryManager.java @@ -22,110 +22,130 @@ import java.util.Collections; import java.util.List; import org.apache.tapestry5.ioc.RegistryBuilder; -import org.junit.runners.model.InitializationError; /** - * Helper class used by the {@link TapestryIOCJUnit4ClassRunner} to manage the test registry + * Helper class used by the {@link TapestryIOCJUnitExtension} to manage the test registry */ -public class TestRegistryManager { - private final Registry annotation; - private final List<Method> moduleDefFactories; - - private org.apache.tapestry5.ioc.Registry registry; - - public TestRegistryManager(Class<?> type) throws InitializationError { - super(); - - Registry annotation = type.getAnnotation(Registry.class); - if (annotation == null) { - throw new InitializationError(type.getName() + " does not specify a @Registry"); - } - - this.annotation = annotation; - this.moduleDefFactories = findModuleDefFactories(type); - } - - protected List<Method> findModuleDefFactories(Class<?> type) throws InitializationError { - List<Method> factoryMethods = new ArrayList<Method>(); - for (Method method : type.getMethods()) { - if (method.getAnnotation(ModuleDef.class) != null) { - validateModuleDefMethod(method); - factoryMethods.add(method); - } - } - return factoryMethods.isEmpty() ? Collections.<Method> emptyList() : factoryMethods; - } - - protected void validateModuleDefMethod(Method method) throws InitializationError { - int modifiers = method.getModifiers(); - if (method.getParameterTypes().length != 0 - || !Modifier.isStatic(modifiers) - || !Modifier.isPublic(modifiers)) { - - throw new InitializationError( - String.format("@ModuleDef method %s must be public static and accept no arguments", - method.getName())); - } - if (!org.apache.tapestry5.ioc.def.ModuleDef.class.isAssignableFrom(method.getReturnType())) { - throw new InitializationError( - String.format("@ModuleDef method %s return type %s is not valid", - method.getName(), method.getReturnType().getName())); - } - } - - /** - * Get the existing registry or create one if required. - * @return The test Registry - * @throws Exception - */ - public org.apache.tapestry5.ioc.Registry getOrCreateRegistry() throws Exception { - if (registry == null) { - RegistryBuilder builder = new RegistryBuilder(); - if (annotation.modules() != null) { - builder.add(annotation.modules()); - } - for (Method moduleDefFactory : moduleDefFactories) { - try { - org.apache.tapestry5.ioc.def.ModuleDef moduleDef = - (org.apache.tapestry5.ioc.def.ModuleDef) moduleDefFactory.invoke(null); - - builder.add(moduleDef); - } catch (InvocationTargetException e) { - if (e.getTargetException() instanceof Exception) { - throw (Exception) e.getTargetException(); - } - throw e; - } - } - registry = builder.build(); - registry.performRegistryStartup(); - } - return registry; - } - - /** - * Notify that the current test method has completed - */ - public void afterTestMethod() { - if (annotation.shutdown() == RegistryShutdownType.AFTER_METHOD) { - shutdownRegistry(); - } - } - - /** - * Notify that the current test class has completed - */ - public void afterTestClass() { - if (annotation.shutdown() == RegistryShutdownType.AFTER_CLASS) { - shutdownRegistry(); - } - } - - protected void shutdownRegistry() { - try { - registry.shutdown(); - } finally { - registry = null; - } - } +public class TestRegistryManager +{ + private final Registry annotation; + private final List<Method> moduleDefFactories; + + private org.apache.tapestry5.ioc.Registry registry; + + public TestRegistryManager(Class<?> type) throws RuntimeException + { + super(); + + Registry annotation = type.getAnnotation(Registry.class); + if (annotation == null) + { throw new RuntimeException(type.getName() + " does not specify a @Registry"); } + + this.annotation = annotation; + this.moduleDefFactories = findModuleDefFactories(type); + } + + protected List<Method> findModuleDefFactories(Class<?> type) throws RuntimeException + { + List<Method> factoryMethods = new ArrayList<Method>(); + for (Method method : type.getMethods()) + { + if (method.getAnnotation(ModuleDef.class) != null) + { + validateModuleDefMethod(method); + factoryMethods.add(method); + } + } + return factoryMethods.isEmpty() ? Collections.<Method> emptyList() : factoryMethods; + } + + protected void validateModuleDefMethod(Method method) throws RuntimeException + { + int modifiers = method.getModifiers(); + if (method.getParameterTypes().length != 0 || !Modifier.isStatic(modifiers) + || !Modifier.isPublic(modifiers)) + { + + throw new RuntimeException(String.format( + "@ModuleDef method %s must be public static and accept no arguments", + method.getName())); + } + if (!org.apache.tapestry5.ioc.def.ModuleDef.class.isAssignableFrom(method.getReturnType())) + { + throw new RuntimeException( + String.format("@ModuleDef method %s return type %s is not valid", + method.getName(), method.getReturnType().getName())); + } + } + + /** + * Get the existing registry or create one if required. + * + * @return The test Registry + * @throws Exception + */ + public org.apache.tapestry5.ioc.Registry getOrCreateRegistry() throws Exception + { + if (registry == null) + { + RegistryBuilder builder = new RegistryBuilder(); + if (annotation.modules() != null) + { + builder.add(annotation.modules()); + } + for (Method moduleDefFactory : moduleDefFactories) + { + try + { + org.apache.tapestry5.ioc.def.ModuleDef moduleDef = (org.apache.tapestry5.ioc.def.ModuleDef) moduleDefFactory + .invoke(null); + + builder.add(moduleDef); + } + catch (InvocationTargetException e) + { + if (e.getTargetException() instanceof Exception) + { throw (Exception) e.getTargetException(); } + throw e; + } + } + registry = builder.build(); + registry.performRegistryStartup(); + } + return registry; + } + + /** + * Notify that the current test method has completed + */ + public void afterTestMethod() + { + if (annotation.shutdown() == RegistryShutdownType.AFTER_METHOD) + { + shutdownRegistry(); + } + } + + /** + * Notify that the current test class has completed + */ + public void afterTestClass() + { + if (annotation.shutdown() == RegistryShutdownType.AFTER_CLASS) + { + shutdownRegistry(); + } + } + + protected void shutdownRegistry() + { + try + { + registry.shutdown(); + } + finally + { + registry = null; + } + } }
