001// Generated by delombok at Sun Jul 30 17:21:56 UTC 2023
002package de.cuioss.test.jsf.junit5;
003
004import java.io.Serializable;
005import java.util.Optional;
006import java.util.Set;
007import javax.inject.Named;
008import org.junit.jupiter.api.BeforeEach;
009import org.junit.jupiter.api.Test;
010import de.cuioss.test.valueobjects.api.ObjectContractTestSupport;
011import de.cuioss.test.valueobjects.api.contracts.VerifyBeanProperty;
012import de.cuioss.test.valueobjects.api.object.ObjectTestConfig;
013import de.cuioss.test.valueobjects.api.object.ObjectTestContracts;
014import de.cuioss.test.valueobjects.contract.BeanPropertyContractImpl;
015import de.cuioss.test.valueobjects.objects.ConfigurationCallBackHandler;
016import de.cuioss.test.valueobjects.objects.ParameterizedInstantiator;
017import de.cuioss.test.valueobjects.objects.RuntimeProperties;
018import de.cuioss.test.valueobjects.objects.impl.BeanInstantiator;
019import de.cuioss.test.valueobjects.objects.impl.CallbackAwareInstantiator;
020import de.cuioss.test.valueobjects.objects.impl.DefaultInstantiator;
021import de.cuioss.test.valueobjects.util.AnnotationHelper;
022import de.cuioss.test.valueobjects.util.ObjectContractHelper;
023import de.cuioss.tools.reflect.MoreReflection;
024
025/**
026 * Base class for testing {@link Named} beans. The test runs implicitly
027 * {@link VerifyBeanProperty}, therefore the annotation is optional, but it can
028 * be used for further configuration.
029 * <p>
030 * As default all {@link ObjectTestContracts} a run, see
031 * {@link #shouldImplementObjectContracts()}
032 * </p>
033 * <p>
034 * Documentation on how to setup the generator can be found at
035 * {@link AbstractPropertyAwareFacesTest}
036 * </p>
037 * <p>
038 * Documentation on the setup of the JSF-related test-infrastructure can be
039 * found at {@link EnableJsfEnvironment}
040 * </p>
041 * <p>
042 * It acts as an {@link ConfigurationCallBackHandler}, saying after
043 * initialization and prior to testing the method {@link #configure(Object)}
044 * will be called allowing the concrete test-class to do some specific
045 * configuration e.g. calling init-methods and such.
046 * </p>
047 * <p>
048 * You can easily access pre-configured instance by calling {@link #anyBean()}.
049 * </p>
050 *
051 * @author Oliver Wolff
052 * @param <T> identifying the type to be tested is usually but not necessarily
053 *            at least {@link Serializable}.
054 */
055public abstract class AbstractBeanTest<T> extends AbstractPropertyAwareFacesTest<T> implements ObjectContractTestSupport {
056    /**
057     * The active object-contracts to be tested
058     */
059    private Set<ObjectTestContracts> activeObjectContracts;
060    /**
061     * Needed {@link ParameterizedInstantiator} for creating test Objects or
062     * {@link #shouldImplementObjectContracts()}
063     */
064    private ParameterizedInstantiator<T> instantiator;
065
066    /**
067     * Initializes the object-test-contracts and the corresponding
068     * {@link ParameterizedInstantiator}
069     */
070    @BeforeEach
071    void before() {
072        this.activeObjectContracts = ObjectContractHelper.handleVetoedContracts(getClass());
073        Optional<VerifyBeanProperty> annotation = MoreReflection.extractAnnotation(getClass(), VerifyBeanProperty.class);
074        ParameterizedInstantiator<T> inlineInstantiator;
075        if (annotation.isPresent()) {
076            var meta = AnnotationHelper.handleMetadataForPropertyTest(getClass(), getPropertyMetadata());
077            inlineInstantiator = new BeanInstantiator<>(new DefaultInstantiator<>(getTargetBeanClass()), new RuntimeProperties(meta));
078        } else {
079            inlineInstantiator = new BeanInstantiator<>(new DefaultInstantiator<>(getTargetBeanClass()), new RuntimeProperties(getPropertyMetadata()));
080        }
081        instantiator = new CallbackAwareInstantiator<>(inlineInstantiator, this);
082    }
083
084    @Override
085    @Test
086    public void shouldImplementObjectContracts() {
087        final var objectTestConfig = this.getClass().getAnnotation(ObjectTestConfig.class);
088        for (final ObjectTestContracts objectTestContracts : this.activeObjectContracts) {
089            objectTestContracts.newObjectTestInstance().assertContract(getInstantiator(), objectTestConfig);
090        }
091    }
092
093    /**
094     * Tests the individually found properties, see {@link VerifyBeanProperty}
095     */
096    @Test
097    void shouldImplementBeanContract() {
098        new BeanPropertyContractImpl<>(getInstantiator()).assertContract();
099    }
100
101    /**
102     * @return a fully configured instance of the bean with
103     *         {@link #configure(Object)} being already called. 'Fully configured'
104     *         is defined as all attributes that can be generated by corresponding
105     *         generators are set
106     */
107    public T anyBean() {
108        return getInstantiator().newInstanceFull();
109    }
110
111    /**
112     * Needed {@link ParameterizedInstantiator} for creating test Objects or
113     * {@link #shouldImplementObjectContracts()}
114     */
115    @java.lang.SuppressWarnings("all")
116    @lombok.Generated
117    protected ParameterizedInstantiator<T> getInstantiator() {
118        return this.instantiator;
119    }
120}