Робоэлектрик 3 с Fabric Crashlytics

Я пытаюсь использовать ShadowClass Crashlytics / Fabric, чтобы тесты Robotlectric 3 не завершились ошибкой. На данный момент у меня есть следующее:

Пользовательский исполнитель тестов, который добавляет класс Shadow для Fabric:

public class TestRunner extends RobolectricGradleTestRunner {
    public TestRunner(Class<?> klass) throws InitializationError {
        super(klass);
    }

    @Override
    protected ShadowMap createShadowMap() {
        return super.createShadowMap()
            .newBuilder().addShadowClass(ShadowFabric.class).build();
    }

    @Override
    public InstrumentationConfiguration createClassLoaderConfig() {
        InstrumentationConfiguration.Builder builder = InstrumentationConfiguration.newBuilder();
        builder.addInstrumentedClass(ShadowFabric.class.getName());
        return builder.build();
    }
}

Класс тени для Fabric:

@Implements(Fabric.class)
public class ShadowFabric {
    @Implementation
    public static Fabric with(Context context, Kit... kits) {
        System.out.println("Shadowing Fabric");
        return null;
    }
}

Мой класс приложения для моего приложения:

public class MyApp extends Application {
    @Override
    public void onCreate() {
        setupCrashlytics();
    }
    protected void setupCrashlytics() {
        Crashlytics crashlyticsKit = new Crashlytics.Builder().core(new CrashlyticsCore.Builder().disabled(BuildConfig.DEBUG).build()).build();
        // Initialize Fabric with the debug-disabled crashlytics.
        Fabric.with(this, crashlyticsKit);
    }
}

И вот тест, который проходит в Debug (потому что Crashlytics отключен на нем), но терпит неудачу в режиме выпуска, потому что ShadowClass работает некорректно:

@RunWith(TestRunner.class)
@Config(constants = BuildConfig.class, sdk=21, packageName="com.my.release.package.name", shadows={ShadowFabric.class})
public class MyTest {
    @Test
    public void testGreenDAOsave() {
        // blah
    }
}

Ошибка, которую я получаю с Crashlytics / Fabric во время теста, следующая:

STANDARD_ERROR
io.fabric.sdk.android.services.concurrency.UnmetDependencyException: com.crashlytics.android.core.CrashlyticsMissingDependencyException:
This app relies on Crashlytics. Please sign up for access at https://fabric.io/sign_up
install an Android build tool and ask a team member to invite you to this app's organization.

Трассировка стека показывает, что вызывается MyApp.setupCrashlytics (), а Fabric.with () не работает.

1) ДА, приложение зарегистрировано в Crashlytics.

2) ДА, я обратился в службу поддержки Crashlytics по электронной почте. Мне сказали: «Робоэлектрик не поддерживается».

Из того, что я вижу, мне просто нужно заставить работать теневой класс, и тогда Crashlytics будет затенен, а не инициализирован.

Мы будем очень благодарны за идеи / помощь!


comment
попробуйте Fabric.class вместо ShadowFabric.class в builder.addInstrumentedClass(ShadowFabric.class.getName());   -  person nenick    schedule 03.05.2016


Ответы (1)


Это мой обычный совет, как написать тест против чего-то не поддающегося тестированию.

Извлеките инициализацию Fabric в защищенный метод:

public class <MyApplicationName> {

public void onCreate() {
   initFabric();
}

@VisibileForTesting
void initFabric() {
....
}
}

Создайте Test<MayApplicationName> класс в тестовых источниках (тот же пакет и переопределите инициализацию Fabric:

public class Test<MyApplicationName> {
void initFabric() {
//nothing to do
}
}

Везде, где вам нужно использовать Fabric, используйте DI (Dependency Injection), чтобы имитировать Fabric в тестах. Более того, я бы посоветовал вам создать класс Analytics / Crash / Distribution и скрыть использование Fabric от всего приложения.

И, наконец, вы оставили классы, которые обертывают / скрывают Ткань. Здесь вы можете написать собственную тень, шпионить за реальным объектом или оставить его непроверенным. И вы уже безуспешно пытались написать кастомную тень, кроме того, шпионство здесь не вариант.

Удачного кодирования!

person Eugen Martynov    schedule 02.05.2016