com.fitbur.jestify.junit.spring.injector.NameMockInjector.java Source code

Java tutorial

Introduction

Here is the source code for com.fitbur.jestify.junit.spring.injector.NameMockInjector.java

Source

/*
 * Copyright 2015 Sharmarke Aden <saden1 at gmail.org>.
 *
 * 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 com.fitbur.jestify.junit.spring.injector;

import com.fitbur.jestify.api.Mock;
import com.fitbur.jestify.core.TestContext;
import com.fitbur.jestify.core.TestInjector;
import com.fitbur.jestify.core.TestReifier;
import com.fitbur.jestify.core.descriptor.DescriptorKey;
import com.fitbur.jestify.core.descriptor.FieldDescriptor;
import com.fitbur.jestify.core.descriptor.ParameterDescriptor;
import static com.google.common.base.Preconditions.checkArgument;
import java.lang.reflect.Field;
import java.lang.reflect.Parameter;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.Optional;
import javax.inject.Provider;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.ResolvableType;

/**
 *
 * @author saden1
 */
public class NameMockInjector implements TestInjector {

    private final TestContext context;
    private final TestReifier testReifier;
    private final AnnotationConfigApplicationContext applicationContext;
    private final FieldDescriptor fieldDescriptor;
    private final Object[] arguments;

    public NameMockInjector(TestContext context, TestReifier testReifier,
            AnnotationConfigApplicationContext applicationContext, FieldDescriptor fieldDescriptor,
            Object[] arguments) {
        this.context = context;
        this.testReifier = testReifier;
        this.applicationContext = applicationContext;
        this.fieldDescriptor = fieldDescriptor;
        this.arguments = arguments;
    }

    @Override
    public void inject() {
        Map<DescriptorKey, ParameterDescriptor> parameterDescriptors = context.getParamaterDescriptors();
        Field field = fieldDescriptor.getField();
        Type fieldType = field.getGenericType();

        Mock mock = fieldDescriptor.getMock().get();
        String mockName = mock.name();
        DescriptorKey descriptorKey = new DescriptorKey(fieldType, mockName);

        ParameterDescriptor parameterDescriptor = parameterDescriptors.get(descriptorKey);

        checkArgument(parameterDescriptor != null,
                "Can not mock field '%s'. Could not find class under test constructor "
                        + "argument with the name '%s'.",
                field.getName(), mockName);

        Parameter parameter = parameterDescriptor.getParameter();
        Integer index = parameterDescriptor.getIndex();
        Type parameterType = parameter.getParameterizedType();

        checkArgument(fieldType.equals(parameterType),
                "Can not mock field '%s'. Test class field type '%s' and class under test "
                        + "constructor parameter type '%s' with name '%s' do not match.",
                field.getName(), field.getGenericType(), parameterType, mockName);

        ResolvableType resolver = ResolvableType.forType(parameterType);

        Class rawType;

        if (resolver.hasGenerics()) {
            if (resolver.isAssignableFrom(Provider.class) || resolver.isAssignableFrom(Optional.class)) {
                rawType = resolver.getRawClass();
            } else {
                rawType = resolver.resolve();
            }
        } else {
            rawType = (Class) parameterType;
        }

        checkArgument(arguments[index] == null,
                "Can not mock field '%s'. Multipe test class fields have the same index of '%d'", field.getName(),
                index);

        Object instance = testReifier.reifyField(fieldDescriptor, parameterDescriptor);

        arguments[index] = instance;
    }

}