Skip to content

Commit

Permalink
Refactoring: extracted new TypeConversion class from Utilities.
Browse files Browse the repository at this point in the history
  • Loading branch information
rliesenfeld committed Jan 18, 2020
1 parent 8dff42a commit d2277db
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 78 deletions.
5 changes: 2 additions & 3 deletions main/src/mockit/internal/expectations/mocking/MockedType.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ private Object getProvidedInjectableValue(@Nullable Injectable annotation) {
// Not supported, do nothing.
}
else {
return Utilities.convertFromString(injectableClass, value);
return TypeConversion.convertFromString(injectableClass, value);
}
}
}
Expand Down Expand Up @@ -173,8 +173,7 @@ boolean isMockableType() {
return false;
}

Type mockedType = declaredType;
Class<?> classType = Utilities.getClassType(mockedType);
Class<?> classType = Utilities.getClassType(declaredType);

if (isUnmockableJREType(classType)) {
return false;
Expand Down
4 changes: 2 additions & 2 deletions main/src/mockit/internal/injection/TestedField.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Object getExistingTestedInstanceIfApplicable(@Nonnull Object testClassInstance)
String providedValue = metadata.value();

if (!providedValue.isEmpty()) {
testedObject = Utilities.convertFromString(targetClass, providedValue);
testedObject = TypeConversion.convertFromString(targetClass, providedValue);
}

createAutomatically = testedObject == null && !isFinal(testedField.getModifiers());
Expand All @@ -55,4 +55,4 @@ Object getExistingTestedInstanceIfApplicable(@Nonnull Object testClassInstance)
void setInstance(@Nonnull Object testClassInstance, @Nullable Object testedInstance) {
setFieldValue(testedField, testClassInstance, testedInstance);
}
}
}
4 changes: 2 additions & 2 deletions main/src/mockit/internal/injection/TestedParameter.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Object getExistingTestedInstanceIfApplicable(@Nonnull Object testClassInstance)

if (!providedValue.isEmpty()) {
Class<?> parameterClass = testMethod.getParameterClass(parameterIndex);
testedObject = Utilities.convertFromString(parameterClass, providedValue);
testedObject = TypeConversion.convertFromString(parameterClass, providedValue);

if (testedObject != null) {
testMethod.setParameterValue(parameterIndex, testedObject);
Expand All @@ -51,4 +51,4 @@ Object getExistingTestedInstanceIfApplicable(@Nonnull Object testClassInstance)
void setInstance(@Nonnull Object testClassInstance, @Nullable Object testedInstance) {
testMethod.setParameterValue(parameterIndex, testedInstance);
}
}
}
87 changes: 87 additions & 0 deletions main/src/mockit/internal/util/TypeConversion.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright (c) 2006 JMockit developers
* This file is subject to the terms of the MIT license (see LICENSE.txt).
*/
package mockit.internal.util;

import javax.annotation.*;
import java.math.*;
import java.util.concurrent.atomic.*;

import static mockit.internal.util.AutoBoxing.*;

public final class TypeConversion {
private TypeConversion() {}

@Nullable
public static Object convertFromString(@Nonnull Class<?> targetType, @Nonnull String value) {
if (targetType == String.class) {
return value;
}
else if (isCharacter(targetType)) {
return value.charAt(0);
}
else if (targetType.isPrimitive() || isWrapperOfPrimitiveType(targetType)) {
return newWrapperInstance(targetType, value);
}
else if (targetType == BigDecimal.class) {
return new BigDecimal(value.trim());
}
else if (targetType == BigInteger.class) {
return new BigInteger(value.trim());
}
else if (targetType == AtomicInteger.class) {
return new AtomicInteger(Integer.parseInt(value.trim()));
}
else if (targetType == AtomicLong.class) {
return new AtomicLong(Long.parseLong(value.trim()));
}
else if (targetType.isEnum()) {
//noinspection unchecked
return enumValue(targetType, value);
}

return null;
}

private static boolean isCharacter(@Nonnull Class<?> targetType) {
return targetType == char.class || targetType == Character.class;
}

@Nonnull
private static Object newWrapperInstance(@Nonnull Class<?> targetType, @Nonnull String value) {
String trimmedValue = value.trim();

try {
if (targetType == int.class || targetType == Integer.class) {
return Integer.valueOf(trimmedValue);
}
else if (targetType == long.class || targetType == Long.class) {
return Long.valueOf(trimmedValue);
}
else if (targetType == short.class || targetType == Short.class) {
return Short.valueOf(trimmedValue);
}
else if (targetType == byte.class || targetType == Byte.class) {
return Byte.valueOf(trimmedValue);
}
else if (targetType == double.class || targetType == Double.class) {
return Double.valueOf(trimmedValue);
}
else if (targetType == float.class || targetType == Float.class) {
return Float.valueOf(trimmedValue);
}
}
catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid value \"" + trimmedValue + "\" for " + targetType);
}

return Boolean.valueOf(trimmedValue);
}

@Nonnull
private static <E extends Enum<E>> Object enumValue(Class<?> targetType, @Nonnull String value) {
@SuppressWarnings("unchecked") Class<E> enumType = (Class<E>) targetType;
return Enum.valueOf(enumType, value);
}
}
72 changes: 1 addition & 71 deletions main/src/mockit/internal/util/Utilities.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,12 @@
*/
package mockit.internal.util;

import javax.annotation.*;
import java.io.*;
import java.lang.reflect.*;
import java.math.*;
import java.net.*;
import java.security.*;
import java.util.*;
import java.util.concurrent.atomic.*;
import javax.annotation.*;

import static java.lang.reflect.Modifier.isPublic;

import static mockit.internal.reflection.ParameterReflection.*;
import static mockit.internal.util.AutoBoxing.*;

/**
* Miscellaneous utility constants and methods.
Expand Down Expand Up @@ -83,69 +76,6 @@ public static boolean containsReference(@Nonnull List<?> references, @Nullable O
return false;
}

@Nullable
public static Object convertFromString(@Nonnull Class<?> targetType, @Nonnull String value) {
if (targetType == String.class) {
return value;
}
else if (isCharacter(targetType)) {
return value.charAt(0);
}
else if (targetType.isPrimitive()) {
return newWrapperInstanceForPrimitiveType(targetType, value);
}
else if (isWrapperOfPrimitiveType(targetType)) {
return newWrapperInstance(targetType, value);
}
else if (targetType == BigDecimal.class) {
return new BigDecimal(value.trim());
}
else if (targetType == BigInteger.class) {
return new BigInteger(value.trim());
}
else if (targetType == AtomicInteger.class) {
return new AtomicInteger(Integer.parseInt(value.trim()));
}
else if (targetType == AtomicLong.class) {
return new AtomicLong(Long.parseLong(value.trim()));
}
else if (targetType.isEnum()) {
//noinspection unchecked
return enumValue(targetType, value);
}

return null;
}

private static boolean isCharacter(@Nonnull Class<?> targetType) {
return targetType == char.class || targetType == Character.class;
}

@Nonnull
private static Object newWrapperInstanceForPrimitiveType(@Nonnull Class<?> targetType, @Nonnull String value) {
Class<?> wrapperClass = getWrapperType(targetType);
assert wrapperClass != null;
return newWrapperInstance(wrapperClass, value);
}

@Nonnull
private static Object newWrapperInstance(@Nonnull Class<?> wrapperClass, @Nonnull String value) {
for (Constructor<?> constructor : wrapperClass.getDeclaredConstructors()) {
if (isPublic(constructor.getModifiers()) && getTypeOfFirstAndOnlyParameter(constructor) == String.class) {
//noinspection OverlyBroadCatchBlock
try { return constructor.newInstance(value.trim()); } catch (Exception ignore) {}
}
}

throw new RuntimeException("Unable to instantiate " + wrapperClass + " with value \"" + value + '"');
}

@Nonnull
private static <E extends Enum<E>> Object enumValue(Class<?> targetType, @Nonnull String value) {
@SuppressWarnings("unchecked") Class<E> enumType = (Class<E>) targetType;
return Enum.valueOf(enumType, value);
}

@Nonnull
public static String getClassFileLocationPath(@Nonnull Class<?> aClass) {
CodeSource codeSource = aClass.getProtectionDomain().getCodeSource();
Expand Down
17 changes: 17 additions & 0 deletions main/test/mockit/InjectableParameterTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,23 @@

public final class InjectableParameterTest
{
@Test
public void injectableParametersOfPrimitiveTypes(
@Injectable("123") int i, @Injectable("5") long l, @Injectable("-45 ") short s, @Injectable(" 127") byte b,
@Injectable("true") boolean f1, @Injectable(" TRUE ") boolean f2, @Injectable("A") char c,
@Injectable(" 1.23") float f, @Injectable("-1.23") double d
) {
assertEquals(123, i);
assertEquals(5L, l);
assertEquals(-45, s);
assertEquals(127, b);
assertTrue(f1);
assertTrue(f2);
assertEquals('A', c);
assertEquals(1.23F, f, 0.0F);
assertEquals(-1.23, d, 0.0);
}

@Test
public void injectableParametersOfWrapperTypes(
@Injectable("123") Integer i, @Injectable("5") Long l, @Injectable("-45 ") Short s, @Injectable(" 127") Byte b,
Expand Down

0 comments on commit d2277db

Please sign in to comment.