private void registerTypeVariableIfNotPresent(TypeVariable<?> typeVariable) { if (!contextualActualTypeParameters.containsKey(typeVariable)) { contextualActualTypeParameters.put(typeVariable, boundsOf(typeVariable)); // logger.log("For '" + typeVariable.getGenericDeclaration() + "' found type variable : { '" + typeVariable + "(" + System.identityHashCode(typeVariable) + ")" + "' : '" + boundsOf(typeVariable) + "' }"); } }
/** * @return Actual type arguments matching the type variables of the raw type represented by this {@link GenericMetadataSupport} instance. */ public Map<TypeVariable<?>, Type> actualTypeArguments() { TypeVariable<?>[] typeParameters = rawType().getTypeParameters(); LinkedHashMap<TypeVariable<?>, Type> actualTypeArguments = new LinkedHashMap<TypeVariable<?>, Type>(); for (TypeVariable<?> typeParameter : typeParameters) { Type actualType = getActualTypeArgumentFor(typeParameter); actualTypeArguments.put(typeParameter, actualType); // logger.log("For '" + rawType().getCanonicalName() + "' returning explicit TypeVariable : { '" + typeParameter + "(" + System.identityHashCode(typeParameter) + ")" + "' : '" + actualType +"' }"); } return actualTypeArguments; }
/** * @return Returns true if metadata knows about extra-interfaces {@link #extraInterfaces()} <strong>if relevant</strong>. */ public boolean hasRawExtraInterfaces() { return rawExtraInterfaces().length > 0; }
/** * Retrieve the expected type when it came from a primitive. If the type cannot be retrieve, return null. * * @param invocation the current invocation * @param returnType the expected return type * @return the type or null if not found */ private Class<?> findTypeFromGeneric(final InvocationOnMock invocation, final TypeVariable returnType) { // Class level final MockCreationSettings mockSettings = MockUtil.getMockHandler(invocation.getMock()).getMockSettings(); final GenericMetadataSupport returnTypeSupport = GenericMetadataSupport .inferFrom(mockSettings.getTypeToMock()) .resolveGenericReturnType(invocation.getMethod()); final Class<?> rawType = returnTypeSupport.rawType(); // Method level if (rawType == Object.class) { return findTypeFromGenericInArguments(invocation, returnType); } return rawType; }
/** * Registers the type variables for the given type and all of its superclasses and superinterfaces. */ protected void registerAllTypeVariables(Type classType) { Queue<Type> typesToRegister = new LinkedList<Type>(); Set<Type> registeredTypes = new HashSet<Type>(); typesToRegister.add(classType); while (!typesToRegister.isEmpty()) { Type typeToRegister = typesToRegister.poll(); if (typeToRegister == null || registeredTypes.contains(typeToRegister)) { continue; } registerTypeVariablesOn(typeToRegister); registeredTypes.add(typeToRegister); Class<?> rawType = extractRawTypeOf(typeToRegister); typesToRegister.add(rawType.getGenericSuperclass()); typesToRegister.addAll(Arrays.asList(rawType.getGenericInterfaces())); } }
private MockSettings withSettingsUsing(GenericMetadataSupport returnTypeGenericMetadata, MockCreationSettings parentMockSettings) { MockSettings mockSettings = returnTypeGenericMetadata.hasRawExtraInterfaces() ? withSettings().extraInterfaces(returnTypeGenericMetadata.rawExtraInterfaces()) : withSettings(); return propagateSerializationSettings(mockSettings, parentMockSettings) .defaultAnswer(returnsDeepStubsAnswerUsing(returnTypeGenericMetadata)); }
public Object answer(InvocationOnMock invocation) throws Throwable { GenericMetadataSupport returnTypeGenericMetadata = actualParameterizedType(invocation.getMock()).resolveGenericReturnType(invocation.getMethod()); Class<?> rawType = returnTypeGenericMetadata.rawType(); if (!mockitoCore().isTypeMockable(rawType)) { return delegate().returnValueFor(rawType); } return deepStub(invocation, returnTypeGenericMetadata); }
@Override public Class<?> rawType() { Class<?> rawComponentType = genericArrayType.rawType(); StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < arity; i++) { stringBuilder.append("["); } try { return Class.forName(stringBuilder.append("L").append(rawComponentType.getName()).append(";").toString(), false, rawComponentType.getClassLoader()); } catch (ClassNotFoundException e) { throw new IllegalStateException("This was not supposed to happend", e); } } }
protected void registerTypeParametersOn(TypeVariable<?>[] typeParameters) { for (TypeVariable<?> type : typeParameters) { registerTypeVariableIfNotPresent(type); } }
protected Type getActualTypeArgumentFor(TypeVariable<?> typeParameter) { Type type = this.contextualActualTypeParameters.get(typeParameter); if (type instanceof TypeVariable) { TypeVariable<?> typeVariable = (TypeVariable<?>) type; return getActualTypeArgumentFor(typeVariable); } return type; }
protected Class<?> extractRawTypeOf(Type type) { if (type instanceof Class) { return (Class<?>) type; } if (type instanceof ParameterizedType) { return (Class<?>) ((ParameterizedType) type).getRawType(); } if (type instanceof BoundedType) { return extractRawTypeOf(((BoundedType) type).firstBound()); } if (type instanceof TypeVariable) { /* * If type is a TypeVariable, then it is needed to gather data elsewhere. Usually TypeVariables are declared * on the class definition, such as such as List<E>. */ return extractRawTypeOf(contextualActualTypeParameters.get(type)); } throw new MockitoException("Raw extraction not supported for : '" + type + "'"); }
protected GenericMetadataSupport actualParameterizedType(Object mock) { CreationSettings mockSettings = (CreationSettings) MockUtil.getMockHandler(mock).getMockSettings(); return GenericMetadataSupport.inferFrom(mockSettings.getTypeToMock()); }
/** * Creates a mock using the Generics Metadata. * * <li>Finally as we want to mock the actual type, but we want to pass along the contextual generics meta-data * that was resolved for the current return type, for this to happen we associate to the mock an new instance of * {@link ReturnsDeepStubs} answer in which we will store the returned type generic metadata. * * @param returnTypeGenericMetadata The metadata to use to create the new mock. * @param parentMock The parent of the current deep stub mock. * @return The mock */ private Object newDeepStubMock(GenericMetadataSupport returnTypeGenericMetadata, Object parentMock) { MockCreationSettings parentMockSettings = MockUtil.getMockSettings(parentMock); return mockitoCore().mock( returnTypeGenericMetadata.rawType(), withSettingsUsing(returnTypeGenericMetadata, parentMockSettings) ); }
/** * @param typeParameter The TypeVariable parameter * @return A {@link BoundedType} for easy bound information, if first bound is a TypeVariable * then retrieve BoundedType of this TypeVariable */ private BoundedType boundsOf(TypeVariable<?> typeParameter) { if (typeParameter.getBounds()[0] instanceof TypeVariable) { return boundsOf((TypeVariable<?>) typeParameter.getBounds()[0]); } return new TypeVarBoundedType(typeParameter); }
protected void registerTypeVariablesOn(Type classType) { if (!(classType instanceof ParameterizedType)) { return; } ParameterizedType parameterizedType = (ParameterizedType) classType; TypeVariable<?>[] typeParameters = ((Class<?>) parameterizedType.getRawType()).getTypeParameters(); Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); for (int i = 0; i < actualTypeArguments.length; i++) { TypeVariable<?> typeParameter = typeParameters[i]; Type actualTypeArgument = actualTypeArguments[i]; // Prevent registration of a cycle of TypeVariables. This can happen when we are processing // type parameters in a Method, while we already processed the type parameters of a class. if (actualTypeArgument instanceof TypeVariable && contextualActualTypeParameters.containsKey(typeParameter)) { continue; } if (actualTypeArgument instanceof WildcardType) { contextualActualTypeParameters.put(typeParameter, boundsOf((WildcardType) actualTypeArgument)); } else if (typeParameter != actualTypeArgument) { contextualActualTypeParameters.put(typeParameter, actualTypeArgument); } // logger.log("For '" + parameterizedType + "' found type variable : { '" + typeParameter + "(" + System.identityHashCode(typeParameter) + ")" + "' : '" + actualTypeArgument + "(" + System.identityHashCode(typeParameter) + ")" + "' }"); } }
/** * @param wildCard The WildCard type * @return A {@link BoundedType} for easy bound information, if first bound is a TypeVariable * then retrieve BoundedType of this TypeVariable */ private BoundedType boundsOf(WildcardType wildCard) { /* * According to JLS(http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.5.1): * - Lower and upper can't coexist: (for instance, this is not allowed: <? extends List<String> & super MyInterface>) * - Multiple bounds are not supported (for instance, this is not allowed: <? extends List<String> & MyInterface>) */ WildCardBoundedType wildCardBoundedType = new WildCardBoundedType(wildCard); if (wildCardBoundedType.firstBound() instanceof TypeVariable) { return boundsOf((TypeVariable<?>) wildCardBoundedType.firstBound()); } return wildCardBoundedType; }