Как тестировать экраны, требующие авторизации? Эспрессо + Моквеб-сервер

Я создаю тесты пользовательского интерфейса. Чтобы не взаимодействовать с реальным сервером, я использую MockWebServer. Моя цель — эмулировать различные ответы сервера и посмотреть, как на них отреагирует программа в целом. На данный момент я не понимаю, как открывать экраны, требующие авторизации. Конечно, я могу написать код, который будет входить на экран авторизации, а потом переходить в нужное окно. Но это требует дополнительного времени на выполнение теста, а этого хотелось бы избежать. Я бы не хотел издеваться над классами, потому что мне нужно проверить рабочую версию приложения. Как я могу это сделать?

Для DI я использую Кинжал-2. Вот код компонента:

@Singleton
@Component(modules = {
        AvatarsModule.class,
        EncryptionModule.class,
        ApiModule.class,
        WalletsModule.class,
        GeneralModule.class,
        InteractorsModule.class,
        PushNotificationsModule.class,
        AppModule.class
})
public interface AppComponent {
    @Component.Builder
    interface Builder {
        @BindsInstance
        Builder context(Context context);
        AppComponent build();
    }

    void inject(App app);
}

Вот код класса, в котором хранится состояние авторизации:

public class ApiWrapper {
    private Api api;
    private KeyPair keyPair;
    private Account account; 

    ...

    public Flowable<Authorization> authorize(KeyPair tempKeyPair) {
        return api
                .authorize(tempKeyPair.getPublicKeyString().toLowerCase())
                .subscribeOn(Schedulers.io())
                .doOnNext((authorization -> {
                    this.account = authorization.getAccount();
                    this.keyPair = tempKeyPair;
                }));
    }
    ...
}

person Павел Дреманович    schedule 14.08.2019    source источник


Ответы (1)


Если кому еще интересно. Я написал класс InstrumentationTestFacade, в который я поместил объект ApiWrapper с помощью Dagger. Затем InstrumentationTestFacade внедряется в объект Application. Поскольку объект приложения не является синглтоном, утечки ответственности в основном коде нет, но из тестового кода вы можете получить доступ к этому фасаду с помощью следующего кода:

Application application = (Application) InstrumentationRegistry.getInstrumentation().getTargetContext().getApplicationContext();
InstrumentationTestFacade facade = application.getInstrumentationTestFacade();

Ниже приведен пример:

public class InstrumentationTestFacade {
    private LogoutInteractor logoutInteractor;
    private SecurityInteractor securityInteractor;
    private ApiWrapper apiWrapper;

    public InstrumentationTestFacade(
            LogoutInteractor logoutInteractor,
            SecurityInteractor securityInteractor,
            ApiWrapper apiWrapper
    ) {
        this.logoutInteractor = logoutInteractor;
        this.securityInteractor = securityInteractor;
        this.apiWrapper = apiWrapper;
    }

    public void logout() {
        logoutInteractor.logout();
    }

    public ApiWrapper getApiWrapper() {
        return apiWrapper;
    }

    public SecurityInteractor getSecurityInteractor() {
        return this.securityInteractor;
    }
}
public class Application extends MultiDexApplication implements HasActivityInjector, HasServiceInjector {

    ...

    @Inject
    InstrumentationTestFacade instrumentationTestFacade;


    @Override
    public void onCreate() {
        super.onCreate();

        DaggerAppComponent
                .builder()
                .context(this)
                .build()
                .inject(this);

    }

    ...

    public InstrumentationTestFacade getInstrumentationTestFacade() {
        return instrumentationTestFacade;
    }
}
person Павел Дреманович    schedule 18.09.2019