public static void reset(Config config) { Robolectric.application = null; Robolectric.packageManager = null; Robolectric.activityThread = null; ShadowLooper.resetThreadLoopers(); ShadowChoreographer.resetThreadLoopers(); List<Class<?>> klasses = Lists.newArrayList(); klasses.addAll(Arrays.asList(Robolectric.DEFAULT_SHADOW_CLASSES)); klasses.addAll(Arrays.asList(config.shadows())); for (Class<?> klass : klasses) { if (klass.getAnnotation(Implements.class).resetStaticState()) { staticMethod("reset").in(klass).invoke(); } } }
private Class<?> getShadowedClass(Method shadowMethod) { Class<?> shadowingClass = shadowMethod.getDeclaringClass(); if (shadowingClass.equals(Object.class)) { return Object.class; } Implements implementsAnnotation = shadowingClass.getAnnotation(Implements.class); if (implementsAnnotation == null) { throw new RuntimeException(shadowingClass + " has no @" + Implements.class.getSimpleName() + " annotation"); } String shadowedClassName = implementsAnnotation.className(); if (shadowedClassName.isEmpty()) { return implementsAnnotation.value(); } else { try { return shadowingClass.getClassLoader().loadClass(shadowedClassName); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } }
private void verifyClass(final Class<?> shadowClass) { Implements annotation = shadowClass.getAnnotation(Implements.class); Class implementedClass = annotation.value(); if (implementedClass.getName().equals(Robolectric.Anything.class.getName())) return; try { shadowClass.getConstructor(implementedClass); } catch (NoSuchMethodException e) { try { shadowClass.getConstructor(); } catch (NoSuchMethodException e1) { mismatches.add("Missing constructor for " + shadowClass.getSimpleName()); } } String expectedName = ShadowMap.convertToShadowName(implementedClass.getName()); if (!shadowClass.getName().equals(expectedName)) { mismatches.add("Shadow class " + shadowClass.getName() + " didn't have the expected name, should be " + expectedName); } for (Method shadowMethod : shadowClass.getDeclaredMethods()) { verifyMethod(implementedClass, shadowMethod); } }
private static ShadowInfo getShadowInfo(Class<?> shadowClass) { Implements implementsAnnotation = shadowClass.getAnnotation(Implements.class); if (implementsAnnotation == null) { throw new IllegalArgumentException(shadowClass + " is not annotated with @Implements"); } String className = implementsAnnotation.className(); try { if (className.isEmpty()) { className = implementsAnnotation.value().getName(); } ShadowConfig shadowConfig = createShadowConfig(shadowClass.getName(), implementsAnnotation.callThroughByDefault(), implementsAnnotation.inheritImplementationMethods(), implementsAnnotation.looseSignatures()); return new ShadowInfo(className, shadowConfig); } catch (TypeNotPresentException typeLoadingException) { String unloadableClassName = shadowClass.getSimpleName(); if (typeLoadingException.typeName().startsWith("com.google.android.maps")) { warnAbout(unloadableClassName); return null; } else if (isIgnorableClassLoadingException(typeLoadingException)) { //this allows users of the robolectric.jar file to use the non-Google APIs version of the api warnAbout(unloadableClassName); } else { throw typeLoadingException; } } return null; }