2011-08-30 2 views
12

Если я напишу пользовательскую тень для своей активности и зарегистрирую ее с помощью RobolectricTestRunner, будет ли перехват активности Activity с моей пользовательской тенью всякий раз, когда она будет запущена?Как конкретно пользовательские объекты Shadow работают в Robolectric?

Спасибо.

ответ

11

Короткий ответ - нет.

Robolectric избирает, какие классы он перехватывает и инструменты. На момент написания этой статьи, только классы, которые будут инструментированные должны иметь полное Classname матч один из этих селекторов:

android.* 
com.google.android.maps.* 
org.apache.http.impl.client.DefaultRequestDirector 

Вся причина существования Robolectric является то, что классы, представленные в банке броске Android SDK исключения при вызове в JVM (т. е. не на эмуляторе или устройстве). Активность вашего приложения имеет источник, который не является «враждебным» (он, вероятно, не генерирует исключений при вызове методов или конструкторов). Цель Robolectric - дать вам возможность проверить код приложения, который в противном случае был бы невозможным из-за того, как написан SDK. Некоторые из других причин, почему был создан Robolectric, были следующими:

  • В SDK не всегда есть методы, позволяющие запрашивать состояние объектов Android, управляемых кодом вашего приложения. Тени могут быть записаны для обеспечения доступа к этому состоянию.
  • Многие из классов и методов в Android SDK являются окончательными и/или частными или защищенными, что затрудняет создание зависимостей, необходимых вашему программному коду, которые в противном случае были бы доступны для вашего кода приложения.

Код может быть явно изменен на тень любого класса. В прошлом говорилось о том, чтобы извлечь функции затенения в автономную библиотеку, чтобы помочь писать тесты, используя некоторые другие тесты-враждебные api.

Почему вы хотите скрыть свою активность?

+0

Благодарим вас за разъяснение. Причина, по которой я хочу скрыть свою активность, заключается в том, что она запускается моим приложением с вызовом 'startActivityForResult (..)'. У меня есть этот код: ShadowActivity shadowActivity = shadowOf (activityA); \t \t Intent startedIntent = shadowActivity.getNextStartedActivity(); \t \t ShadowIntent shadowIntent = shadowOf (initialIntent); \t \t assertThat (shadowIntent.getComponent(). GetClassName(), equalTo (activityB.class.getName())); 'Я хочу получить представления из activityB. Используя собственный API, я использовал «ActivityMonitor», но я хочу знать, как это сделать, используя Robolectric. – kaneda

2

Как обновление, я смог создать тени своих собственных классов, пока я стараюсь привязать теневой класс до того, как какой-либо возможный загрузчик будет действовать на этот класс. Таким образом, в соответствии с инструкциями, в RoboRunner я сделал:

@Override protected void bindShadowClasses() { 
    Robolectric.bindShadowClass(ShadowLog.class); 
    Robolectric.bindShadowClass(ShadowFlashPlayerFinder.class); 
} 

Я уже говорил, что я обманываю немного? Исходный ответ выше (конечно) правильный. Поэтому я использую это для моего реального класса:

package android.niftyco; 

public class FlashPlayerFinder { 
    .. . 

И мой макет (тень) находится в задней части в моем тестовом пакете, как можно было бы ожидать:

package com.niftyco.android.test; 

@Implements(FlashPlayerFinder.class) 
public class ShadowFlashPlayerFinder { 
    @RealObject private FlashPlayerFinder realFPF; 

    public void __constructor(Context c) { 
     //note the construction 
    } 

    @Implementation 
    public boolean isFlashInstalled() { 
     System.out.print("Let's pretend that Flash is installed\n"); 
     return(true); 
    } 
} 
3

Да, если подкласс RobolectricTestRunner, добавьте настраиваемый пакет в конструктор и загрузите классы Shadow в метод bindShadowClasses. Не нужно использовать андроид. * Трюк пакета.

(Примечание: это с robolectric-1.1)

Есть целый ряд крючков, предусмотренных в RobolectricTestRunner # setupApplicationState, что вы можете переопределить.

Вот моя реализация RobolectricTestRunner.

import org.junit.runners.model.InitializationError; 

import com.android.testFramework.shadows.ShadowLoggerConfig; 
import com.xtremelabs.robolectric.Robolectric; 
import com.xtremelabs.robolectric.RobolectricTestRunner; 

public class RoboRunner extends RobolectricTestRunner { 

public RoboRunner(Class<?> clazz) throws InitializationError { 
    super(clazz); 
    addClassOrPackageToInstrument("package.you're.creating.shadows.of"); 
} 

@Override 
protected void bindShadowClasses() { 
    super.bindShadowClasses(); // as you can see below, you really don't need this 
    Robolectric.bindShadowClass(ShadowClass.class); 
} 

}

Более методы, которые вы можете создать подкласс (от RobolectricTestRunner.class)

/** 
* Override this method to bind your own shadow classes 
*/ 
protected void bindShadowClasses() { 
} 

/** 
* Override this method to reset the state of static members before each test. 
*/ 
protected void resetStaticState() { 
} 

    /** 
* Override this method if you want to provide your own implementation of Application. 
* <p/> 
* This method attempts to instantiate an application instance as specified by the AndroidManifest.xml. 
* 
* @return An instance of the Application class specified by the ApplicationManifest.xml or an instance of 
*   Application if not specified. 
*/ 
protected Application createApplication() { 
    return new ApplicationResolver(robolectricConfig).resolveApplication(); 
} 

Вот где они называются в Robolectric TestRunner:

public void setupApplicationState(final RobolectricConfig robolectricConfig) { 
    setupLogging(); 
    ResourceLoader resourceLoader = createResourceLoader(robolectricConfig); 

    Robolectric.bindDefaultShadowClasses(); 
    bindShadowClasses(); 

    resourceLoader.setLayoutQualifierSearchPath(); 
    Robolectric.resetStaticState(); 
    resetStaticState(); 

    DatabaseConfig.setDatabaseMap(this.databaseMap);//Set static DatabaseMap in DBConfig 

    Robolectric.application = ShadowApplication.bind(createApplication(), resourceLoader); 
} 
9

Это значительно изменилось с помощью Robolectric 2. Вы можете указать custom shadows in the configuration вместо написав собственный TestRunner.

Например:

@Config(shadows = {ShadowAudioManager.class, ShadowContextWrapper.class}) 
2

Может быть поздно, но отсюда: org.robolectric.bytecode.Setup, вы могли бы найти более подробно о том, какие классы инструментальными.

public boolean shouldInstrument(ClassInfo classInfo) { 
    if (classInfo.isInterface() || classInfo.isAnnotation() || classInfo.hasAnnotation(DoNotInstrument.class)) { 
     return false; 
    } 

    // allow explicit control with @Instrument, mostly for tests 
    return classInfo.hasAnnotation(Instrument.class) || isFromAndroidSdk(classInfo); 
    } 

    public boolean isFromAndroidSdk(ClassInfo classInfo) { 
    String className = classInfo.getName(); 
    return className.startsWith("android.") 
     || className.startsWith("libcore.") 
     || className.startsWith("dalvik.") 
     || className.startsWith("com.android.internal.") 
     || className.startsWith("com.google.android.maps.") 
     || className.startsWith("com.google.android.gms.") 
     || className.startsWith("dalvik.system.") 
     || className.startsWith("org.apache.http.impl.client.DefaultRequestDirector"); 
    } 
Смежные вопросы