/** * Invoke this utility method in tests to reveal which Android api classes and methods are being invoked * for which there are no shadows or shadow methods. This helps expose which methods are being invoked * either by a third party library or application code which need new shadow methods to be written. Generates * output for the current test only. */ public static void logMissingInvokedShadowMethods() { ShadowWrangler.getInstance().logMissingInvokedShadowMethods(); }
public static ShadowWrangler getInstance() { if (singleton == null) { singleton = new ShadowWrangler(); } return singleton; }
private void injectRealObjectOn(Object shadow, Class<?> shadowClass, Object instance) { MetaShadow metaShadow = getMetaShadow(shadowClass); for (Field realObjectField : metaShadow.realObjectFields) { writeField(shadow, instance, realObjectField); } }
@SuppressWarnings({"unchecked"}) public static <P, R> P shadowOf_(R instance) { return (P) ShadowWrangler.getInstance().shadowOf(instance); }
public Object shadowFor(Object instance) { Field field = getShadowField(instance); Object shadow = readField(instance, field); if (shadow != null) { return shadow; } String shadowClassName = getShadowClassName(instance.getClass()); if (debug) System.out.println("creating new " + shadowClassName + " as shadow for " + instance.getClass().getName()); try { Class<?> shadowClass = loadClass(shadowClassName, instance.getClass().getClassLoader()); Constructor<?> constructor = findConstructor(instance, shadowClass); if (constructor != null) { shadow = constructor.newInstance(instance); } else { shadow = shadowClass.newInstance(); } field.set(instance, shadow); injectRealObjectOn(shadow, shadowClass, instance); return shadow; } catch (InstantiationException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { throw new RuntimeException(e); } }
private static RobolectricClassLoader getDefaultLoader() { if (defaultLoader == null) { defaultLoader = new RobolectricClassLoader(ShadowWrangler.getInstance()); } return defaultLoader; }
public static void bindShadowClass(Class<?> shadowClass) { Implements realClass = shadowClass.getAnnotation(Implements.class); if (realClass == null) { throw new IllegalArgumentException(shadowClass + " is not annotated with @Implements"); } try { ShadowWrangler.getInstance().bindShadowClass(realClass.value(), shadowClass); } catch (TypeNotPresentException typeLoadingException) { String unloadableClassName = shadowClass.getSimpleName(); if (isIgnorableClassLoadingException(typeLoadingException)) { //this allows users of the robolectric.jar file to use the non-Google APIs version of the api if (unloadableClassNames.add(unloadableClassName)) { System.out.println("Warning: an error occurred while binding shadow class: " + unloadableClassName); } } else { throw typeLoadingException; } } }
public static void resetStaticState() { ShadowWrangler.getInstance().silence(); Robolectric.application = new Application(); ShadowBitmapFactory.reset(); ShadowDrawable.reset(); ShadowMediaStore.reset(); ShadowLog.reset(); ShadowContext.clearFilesAndCache(); ShadowLooper.resetThreadLoopers(); ShadowDialog.reset(); ShadowContentResolver.reset(); ShadowLocalBroadcastManager.reset(); ShadowMimeTypeMap.reset(); ShadowPowerManager.reset(); ShadowStatFs.reset(); }
public Object shadowOf(Object instance) { if (instance == null) { throw new NullPointerException("can't get a shadow for null"); } Field field = getShadowField(instance); return readField(instance, field); }
public boolean prepare() { Class<?>[] paramClasses = getParamClasses(); Class<?> originalClass = loadClass(clazz.getName(), classLoader); declaredShadowClass = findDeclaredShadowClassForMethod(originalClass, methodName, paramClasses); if (declaredShadowClass == null) { return false; } if (methodName.equals("<init>")) { methodName = "__constructor__"; } if (instance != null) { shadow = shadowFor(instance); method = getMethod(shadow.getClass(), methodName, paramClasses); } else { shadow = null; method = getMethod(findShadowClass(clazz), methodName, paramClasses); } if (method == null) { if (debug) { System.out.println("No method found for " + clazz + "." + methodName + "(" + Arrays.asList(paramClasses) + ") on " + declaredShadowClass.getName()); } return false; } if ((instance == null) != Modifier.isStatic(method.getModifiers())) { throw new RuntimeException("method staticness of " + clazz.getName() + "." + methodName + " and " + declaredShadowClass.getName() + "." + method.getName() + " don't match"); } method.setAccessible(true); return true; }
private Class<?>[] getParamClasses() { Class<?>[] paramClasses = new Class<?>[paramTypes.length]; for (int i = 0; i < paramTypes.length; i++) { paramClasses[i] = loadClass(paramTypes[i], classLoader); } return paramClasses; }
private static RobolectricClassLoader getDefaultLoader() { if (defaultLoader == null) { defaultLoader = new RobolectricClassLoader(ShadowWrangler.getInstance()); } return defaultLoader; }
private Class<?> findShadowClass(Class<?> originalClass) { String declaredShadowClassName = getShadowClassName(originalClass); if (declaredShadowClassName == null) { return null; } return loadClass(declaredShadowClassName, classLoader); }
/** * Call this constructor in subclasses in order to specify non-default configuration (e.g. location of the * AndroidManifest.xml file, resource directory, and DatabaseMap). * * @param testClass the test class to be run * @param robolectricConfig the configuration data * @param databaseMap the database mapping * @throws InitializationError if junit says so */ protected RobolectricTestRunner(Class<?> testClass, RobolectricConfig robolectricConfig, DatabaseMap databaseMap) throws InitializationError { this(testClass, isInstrumented() ? null : ShadowWrangler.getInstance(), isInstrumented() ? null : getDefaultLoader(), robolectricConfig, databaseMap); }
/** * Call this constructor in subclasses in order to specify non-default configuration (e.g. location of the * AndroidManifest.xml file, resource directory, and DatabaseMap). * * @param testClass the test class to be run * @param robolectricConfig the configuration data * @param databaseMap the database mapping * @throws org.junit.runners.model.InitializationError * if junit says so */ protected RobolectricSimpleRunner(Class<?> testClass, RobolectricConfig robolectricConfig, DatabaseConfig.DatabaseMap databaseMap) throws InitializationError { this(testClass, isInstrumented() ? null : ShadowWrangler.getInstance(), isInstrumented() ? null : getDefaultLoader(), robolectricConfig, databaseMap); }
/** * Call this constructor in subclasses in order to specify non-default configuration (e.g. location of the * AndroidManifest.xml file and resource directory). * * @param testClass the test class to be run * @param robolectricConfig the configuration data * @throws InitializationError if junit says so */ protected RobolectricTestRunner(final Class<?> testClass, final RobolectricConfig robolectricConfig) throws InitializationError { this(testClass, isInstrumented() ? null : ShadowWrangler.getInstance(), isInstrumented() ? null : getDefaultLoader(), robolectricConfig, new SQLiteMap()); }
/** * Call this constructor in subclasses in order to specify non-default configuration (e.g. location of the * AndroidManifest.xml file and resource directory). * * @param testClass the test class to be run * @param robolectricConfig the configuration data * @throws org.junit.runners.model.InitializationError * if junit says so */ protected RobolectricSimpleRunner(final Class<?> testClass, final RobolectricConfig robolectricConfig) throws InitializationError { this(testClass, isInstrumented() ? null : ShadowWrangler.getInstance(), isInstrumented() ? null : getDefaultLoader(), robolectricConfig, new SQLiteMap()); }