001/** 002 * Copyright (C) 2006-2024 Talend Inc. - www.talend.com 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.talend.sdk.component.junit.base.junit5; 017 018import java.lang.annotation.Annotation; 019import java.util.stream.Stream; 020 021import org.junit.jupiter.api.extension.ExtensionContext; 022import org.junit.jupiter.api.extension.ParameterContext; 023import org.junit.jupiter.api.extension.ParameterResolutionException; 024import org.junit.jupiter.api.extension.ParameterResolver; 025import org.junit.jupiter.api.extension.TestInstancePostProcessor; 026 027/** 028 * Helper which ensure the same code is used for the field injections and parameter injections. 029 */ 030public interface JUnit5InjectionSupport extends ParameterResolver, TestInstancePostProcessor { 031 032 Class<? extends Annotation> injectionMarker(); 033 034 default boolean supports(final Class<?> type) { 035 return type.isInstance(this); 036 } 037 038 default Object findInstance(final ExtensionContext extensionContext, final Class<?> type, final Annotation marker) { 039 return findInstance(extensionContext, type); 040 } 041 042 default Object findInstance(final ExtensionContext extensionContext, final Class<?> type) { 043 return this; 044 } 045 046 @Override 047 default boolean supportsParameter(final ParameterContext parameterContext, final ExtensionContext extensionContext) 048 throws ParameterResolutionException { 049 return supports(parameterContext.getParameter().getType()); 050 } 051 052 @Override 053 default Object resolveParameter(final ParameterContext parameterContext, final ExtensionContext extensionContext) 054 throws ParameterResolutionException { 055 return findInstance(extensionContext, parameterContext.getParameter().getType()); 056 } 057 058 @Override 059 default void postProcessTestInstance(final Object testInstance, final ExtensionContext context) { 060 Class<?> testClass = context.getRequiredTestClass(); 061 while (testClass != Object.class) { 062 Stream 063 .of(testClass.getDeclaredFields()) 064 .filter(c -> c.isAnnotationPresent(injectionMarker())) 065 .forEach(f -> { 066 if (!supports(f.getType())) { 067 throw new IllegalArgumentException("@" + injectionMarker() + " not supported on " + f); 068 } 069 if (!f.isAccessible()) { 070 f.setAccessible(true); 071 } 072 try { 073 f.set(testInstance, findInstance(context, f.getType(), f.getAnnotation(injectionMarker()))); 074 } catch (final IllegalAccessException e) { 075 throw new IllegalStateException(e); 076 } 077 }); 078 testClass = testClass.getSuperclass(); 079 } 080 } 081}