Java tutorial
/* * 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; import com.fitbur.jestify.api.Cut; import com.fitbur.jestify.api.Mock; import com.fitbur.jestify.api.Module; import com.fitbur.jestify.core.TestReifier; import com.fitbur.jestify.core.descriptor.CutDescriptor; import com.fitbur.jestify.core.descriptor.FieldDescriptor; import com.fitbur.jestify.core.descriptor.ParameterDescriptor; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Type; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Optional; import javax.inject.Provider; import static org.mockito.AdditionalAnswers.delegatesTo; import org.mockito.MockSettings; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.withSettings; import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE; import org.springframework.beans.factory.support.GenericBeanDefinition; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.core.ResolvableType; /** * * @author Sharmarke Aden <saden1 at gmail.org> */ public class IntegrationTestReifier implements TestReifier<Object[]> { private final AnnotationConfigApplicationContext appContext; private final Object testInstance; public IntegrationTestReifier(AnnotationConfigApplicationContext appContext, Object testInstance) { this.appContext = appContext; this.testInstance = testInstance; } @Override public Object reifyField(FieldDescriptor fieldDescriptor, ParameterDescriptor parameterDescriptor) { return AccessController.doPrivileged((PrivilegedAction<Object>) () -> { try { Object instance; Field field = fieldDescriptor.getField(); Type fieldType = field.getGenericType(); field.setAccessible(true); Optional<Mock> optMock = fieldDescriptor.getMock(); if (optMock.isPresent()) { Mock mock = optMock.get(); Object value = field.get(testInstance); //if the field value is set then create a mock otherwise create a mock //that delegates to the value if (value == null) { MockSettings settings = withSettings().defaultAnswer(mock.answer()); if (mock.extraInterfaces().length > 0) { settings.extraInterfaces(mock.extraInterfaces()); } instance = mock(field.getType(), settings); } else { instance = mock(field.getType(), delegatesTo(value)); } } else { ResolvableType resolver = ResolvableType.forType(fieldType); Class rawType; if (resolver.hasGenerics()) { if (resolver.isAssignableFrom(Provider.class) || resolver.isAssignableFrom(Optional.class)) { rawType = resolver.getRawClass(); } else { rawType = resolver.resolve(); } } else { rawType = (Class) fieldType; } instance = appContext.getBean(rawType); } field.set(testInstance, instance); fieldDescriptor.setInstance(instance); parameterDescriptor.setInstance(instance); return instance; } catch (IllegalAccessException | IllegalArgumentException e) { throw new RuntimeException(e); } }); } @Override public Object reifyCut(CutDescriptor cutDescriptor, Object[] arguments) { return AccessController.doPrivileged((PrivilegedAction<Object>) () -> { try { Cut cut = cutDescriptor.getCut(); Field field = cutDescriptor.getField(); Type fieldType = field.getGenericType(); String fieldName = field.getName(); field.setAccessible(true); Constructor<?> constructor = cutDescriptor.getConstructor(); constructor.setAccessible(true); ResolvableType resolver = ResolvableType.forType(fieldType); Class rawType; if (resolver.hasGenerics()) { if (resolver.isAssignableFrom(Provider.class) || resolver.isAssignableFrom(Optional.class)) { rawType = resolver.getRawClass(); } else { rawType = resolver.resolve(); } } else { rawType = resolver.resolve(); } Module module = testInstance.getClass().getDeclaredAnnotation(Module.class); GenericBeanDefinition bean = new GenericBeanDefinition(); bean.setBeanClass(rawType); bean.setAutowireCandidate(false); bean.setScope(SCOPE_PROTOTYPE); bean.setPrimary(true); bean.setLazyInit(true); bean.setRole(RootBeanDefinition.ROLE_APPLICATION); bean.setAutowireMode(RootBeanDefinition.AUTOWIRE_NO); appContext.registerBeanDefinition(fieldName, bean); if (module != null) { appContext.register(module.value()); } appContext.refresh(); Object instance = appContext.getBean(fieldName, arguments); if (cut.value()) { instance = spy(instance); } field.set(testInstance, instance); return instance; } catch (SecurityException | IllegalAccessException | IllegalArgumentException e) { throw new RuntimeException(e); } }); } }