/* * Copyright (c) 2006 Rogério Liesenfeld * This file is subject to the terms of the MIT license (see LICENSE.txt). */ package mockit.internal.injection; import java.lang.reflect.*; import java.lang.reflect.Type; import javax.annotation.*; import static java.lang.reflect.Modifier.*; import mockit.external.asm.*; import mockit.internal.classGeneration.*; import mockit.internal.expectations.mocking.*; import mockit.internal.injection.constructor.*; import mockit.internal.injection.full.*; import mockit.internal.state.*; public final class TestedObjectCreation { @Nonnull private final InjectionState injectionState; @Nullable private final FullInjection fullInjection; @Nonnull private final Class<?> actualTestedClass; @Nonnull final TestedClass testedClass; TestedObjectCreation( @Nonnull InjectionState injectionState, @Nullable FullInjection fullInjection, @Nonnull Type declaredType, @Nonnull Class<?> declaredClass) { this.injectionState = injectionState; this.fullInjection = fullInjection; actualTestedClass = isAbstract(declaredClass.getModifiers()) ? generateSubclass(declaredType, declaredClass) : declaredClass; testedClass = new TestedClass(declaredType, declaredClass); } @Nonnull private Class<?> generateSubclass(@Nonnull final Type testedType, @Nonnull final Class<?> abstractClass) { Class<?> generatedSubclass = new ImplementationClass<Object>(abstractClass) { @Nonnull @Override protected ClassVisitor createMethodBodyGenerator(@Nonnull ClassReader typeReader) { return new SubclassGenerationModifier(abstractClass, testedType, typeReader, generatedClassName, true); } }.generateClass(); TestRun.mockFixture().registerMockedClass(generatedSubclass); return generatedSubclass; } public TestedObjectCreation( @Nonnull InjectionState injectionState, @Nullable FullInjection fullInjection, @Nonnull Class<?> implementationClass) { this.injectionState = injectionState; this.fullInjection = fullInjection; actualTestedClass = implementationClass; testedClass = new TestedClass(implementationClass, implementationClass); } @Nonnull public Object create() { ConstructorSearch constructorSearch = new ConstructorSearch(injectionState, actualTestedClass, fullInjection != null); Constructor<?> constructor = constructorSearch.findConstructorToUse(); if (constructor == null) { String description = constructorSearch.getDescription(); throw new IllegalArgumentException( "No constructor in tested class that can be satisfied by available injectables" + description); } ConstructorInjection constructorInjection = new ConstructorInjection(testedClass, injectionState, fullInjection, constructor); return constructorInjection.instantiate(constructorSearch.parameterProviders); } }