Android how to check the unit test with powermockito
public void updateProfile(final UserLogin updateUser) {
profileModelImple.updateUser(updateUser)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Object>() {
#Override
public void onCompleted () {
}
#Override
public void onError (Throwable e) {
Timber.e("authenticationModel -> login " + e);
EventBus.getDefault().post(null);
}
#Override
public void onNext (Object user) {
}
});
}
Related
I'm testing RxJava at the moment, and I get confused.
I placed method with Thread.sleep(5000)
into Schedulers.io()
CompositeDisposable compositeDisposable = new CompositeDisposable();
compositeDisposable.add(longOperation()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableCompletableObserver() {
#Override
public void onComplete() {
customToast("long operation done");
}
#Override
public void onError(Throwable e) {
}
}));
I read, we should move long operation into schedulers.io because we can't freeze UI thread, but in this case, I got freeze UI. What is wrong ?
longOperation() have Thread.sleep(5000) inside.
//after edit Callable
private void doSomething() throws InterruptedException {
CompositeDisposable compositeDisposable = new CompositeDisposable();
compositeDisposable.add(Observable.fromCallable(()-> longOperation())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableCompletableObserver() {
#Override
public void onComplete() {
customToast("long operation done");
}
#Override
public void onError(Throwable e) {
}
}));
}
private Completable longOperation() throws InterruptedException {
Thread.sleep(5000);
return Completable.complete();
}
You should be using defer() so that it actually executes on the scheduler instead of when you're trying to create the completable.
private void doSomething() throws InterruptedException {
CompositeDisposable compositeDisposable = new CompositeDisposable();
compositeDisposable.add(Completable.defer(new Callable<CompletableSource>() {
#Override
public CompletableSource call() throws Exception {
return longOperation();
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableCompletableObserver() {
#Override
public void onComplete() {
customToast("long operation done");
}
#Override
public void onError(Throwable e) {
}
}));
}
private Completable longOperation() throws InterruptedException {
Thread.sleep(5000);
return Completable.complete();
}
What is the correct way to implement the tests below using rxjava2?
Given a list of ntp servers, test each one until you succeed.
Example:
time.nist.gov -> timeout
pool.ntp.org -> timeout
time.google.com -> success, get date
time.apple.com -> ignore
I do not want to test all in parallels but one by one. And if all fail, it restarts the test again.
Using only one server, the code I'm using is this:
public void getTime() {
timeObservable = Observable
.fromCallable(new Callable<Date>() {
#Override
public Date call() throws IOException {
return connectAndGetTime(HOST);
}
})
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.doOnError(new Consumer<Throwable>() {
#Override
public void accept(Throwable error) {
Timber.tag(TAG).e(error);
}
})
.retry(5);
timeObservable.subscribe(new Consumer<Date>() {
#Override
public void accept(Date date) {
mDate = date;
}
}, new Consumer<Throwable>() {
#Override
public void accept(Throwable throwable) {
Timber.tag(TAG).e(throwable);
}
});
}
Thanks!
Thanks Alexei, you're right.
Why complicate things?
The end result looks like this:
public void getTime() {
timeObservable = Observable
.fromCallable(new Callable<Date>() {
#Override
public Date call() {
for (String host : Arrays.asList("time.google.com", "time.apple.com", "time.nist.gov")) {
try {
return connectAndGetTime(host);
} catch (Exception e) {
Timber.tag(TAG).d("Sync (%s) fail!", host);
}
}
return null;
}
})
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.doOnError(new Consumer<Throwable>() {
#Override
public void accept(Throwable error) {
Timber.tag(TAG).e(error);
}
})
.retry(5);
timeObservable.subscribe(new Consumer<Date>() {
#Override
public void accept(Date date) {
mDate = date;
}
}, new Consumer<Throwable>() {
#Override
public void accept(Throwable throwable) {
Timber.tag(TAG).e(throwable);
}
});
}
I am trying to make webservie call using retrofit and rxjava 2. i was exploring two different approach to use RxJava2. problem is i am getting response whene i use Observable but it is not working with Flowable. Logs are not getting printed when using Flowable i tried to debug it but its not going inside onNext or onComplete or onError. only onSubscribe gets executed.
1) using observable as return type
new WebRequestManager().getContactObservable(userRequest)
.subscribe(new Observer<ResponseData>() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(ResponseData responseData) {
Log.e(TAG , "data "+responseData.getStatus());
}
#Override
public void onError(Throwable e) {
}
#Override
public void onComplete() {
Log.e(TAG , "data complete");
}
}
);
2) Using flowable as return type
new WebRequestManager().getContactFlowable(userRequest)
.subscribe(new Subscriber<ResponseData>() {
#Override
public void onSubscribe(Subscription s) {
Log.e(TAG , "contact subscription ");
}
#Override
public void onNext(ResponseData responses) {
Log.e(TAG , "contact onNext ");
}
#Override
public void onError(Throwable t) {
}
#Override
public void onComplete() {
Log.e(TAG , "contact onComplete ");
}
});
Rest contact retrofit api
public interface ContactApi {
#POST(WebRequest.GET_CONTACTS)
Flowable<ResponseData> getContactFlowable(#Body UserRequest userRequest);
#POST(WebRequest.GET_CONTACTS)
Observable<ResponseData> getContactObservable(#Body UserRequest userRequest);
}
call to webservice
public Flowable<ResponseData> getContactsData(UserRequest userRequest){
return webRequest.getWebClient().create(ContactApi.class).getContacts(userRequest);
}
public Observable<ResponseData> getContact(UserRequest userRequest){
return webRequest.getWebClient().create(ContactApi.class).getContact(userRequest);
}
getting retrofit instance
public static Retrofit getWebClient(){
//if(okHttpClient == null)
okHttpClient = new OkHttpClient.Builder()
.connectTimeout(120,TimeUnit.SECONDS)
.readTimeout(120,TimeUnit.SECONDS)
.writeTimeout(120,TimeUnit.SECONDS)
.addInterceptor(new WebRequestInterceptor("\"application/json\""))
.build();
// if(client == null)
client = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(okHttpClient)
.addConverterFactory(LoganSquareConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
return client;
}
With Subscribers, you have to call request to get items:
new WebRequestManager().getContactFlowable(userRequest)
.subscribe(new Subscriber<ResponseData>() {
#Override
public void onSubscribe(Subscription s) {
Log.e(TAG , "contact subscription ");
s.request(Long.MAX_VALUE); // <---------------------------------
}
#Override
public void onNext(ResponseData responses) {
Log.e(TAG , "contact onNext ");
}
#Override
public void onError(Throwable t) {
}
#Override
public void onComplete() {
Log.e(TAG , "contact onComplete ");
}
});
See also DisposableSubscriber with its example.
I'm using rx libraries im my app to call some REST api on my server and to show the results on screen.
I'm also following the MVP design pattern. So I have a Presenter and an Interactor classes.
In MainInteractor.java I have the following method:
public Observable<Card> fetchCard(final String clientId, final CardFetchedListener listener) {
Log.i(TAG, "FetchCard method");
// Manipulate the observer
return CARDS
.doOnCompleted(new Action0() {
#Override
public void call() {
Log.d(TAG, "CARDS Completed");
}
})
.flatMap(new Func1<Card, Observable<Card>>() {
#Override
public Observable<Card> call(final Card card) {
return ResourceClient.getInstance(card)
.getIDCard()
.observeOn(AndroidSchedulers.mainThread())
.doOnError(new Action1<Throwable>() {
#Override
public void call(Throwable throwable) {
Log.w(TAG, "interactor -> fetchCard 2", throwable);
}
}
})
.flatMap(new Func1<CardMeta, Observable<Card>>() {
#Override
public Observable<Card> call(CardMeta cardMeta) {
card.setCardMeta(cardMeta);
saveOrUpdateCardToTheDb(card);
return Observable.just(card);
}
})
.doOnCompleted(new Action0() {
#Override
public void call() {
Log.d(TAG, "Completed body");
}
});
}
});
}
In the logs I can see the "Completed Body" string.
The above method is being called by MainPresenter.java class as follows:
interactor.fetchCard(clientId, this)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Card>() {
#Override
public void onCompleted() {
Log.i(TAG, "fetchCard onCompleted");
view.hideProgressDialog();
view.updateCardsAdapter(cards);
}
#Override
public void onError(Throwable e) {
Log.e(TAG, "Fetch Card error ", e);
onFailure(parseThrowable(e));
}
#Override
public void onNext(Card card) {
if (card != null) {
Log.i(TAG, card.getTenant() + " was fetched and will be displayed");
}
}
});
The problem is that the onCompleted method in the Presenter class is never bein called. I have tried to call onCompleted myself and it worked, but the problem is I don't know actually when the observable has finished emitting cards.
What am I doing wrong here?
UPDATE
CARDS is also an observable that contains meta info. It is initialized using
Observable.from(tenants)
.filter(...).flatMap(// I'm using create operator here and it is calling its onCompleted method successflly);
I'm new to rxjava 2 and i'm trying to execute someMethod in the background with a given interval and use the result on the UI thread. Can someone point me where i made mistake in my code or even better provide optimal code that does the job i need?
#Override
protected void onStop() {
subject.onNext(Long.valueOf(10005));
observable.unsubscribeOn(Schedulers.io());
super.onStop();
}
private void initAzimuthUpdater() {
subject = PublishSubject.create();
observable = Observable.interval(500, TimeUnit.MILLISECONDS)
.takeWhile(new Predicate<Long>() {
#Override
public boolean test(#NonNull Long aLong) throws Exception {
Log.d(TAG, "xxxxxxxxxxxx test: " + aLong);
return aLong != Long.valueOf(10005);
}
});
observable.flatMap(new Function<Long, ObservableSource<Float>>() {
#Override
public ObservableSource<Float> apply(#NonNull Long aLong) throws Exception {
return PublishSubject.create(new ObservableOnSubscribe<Float>() {
#Override
public void subscribe(#NonNull ObservableEmitter<Float> e) throws Exception {
e.onNext(someMethod());
}
});
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Float>() {
#Override
public void onSubscribe(#NonNull Disposable d) {
Log.d(TAG, "xxxxxxxx onSubscribe:" + System.currentTimeMillis());
isRunning = true;
}
#Override
public void onNext(#NonNull Float o) {
Log.d(TAG, "xxxxxxxx onNext:" + System.currentTimeMillis());
//update UI
}
#Override
public void onError(#NonNull Throwable e) {
Log.d(TAG, "xxxxxxxx onError:" + System.currentTimeMillis());
}
#Override
public void onComplete() {
Log.d(TAG, "xxxxxxxx onComplete:" + System.currentTimeMillis());
}
});
subject.mergeWith(azimuthObservable);
}
You should use DisposableObserver and subscribeWith, save the Disposable into a CompositeDisposable, then call clear() on it from onStop(). The Observable operators return a new instance so ignoring their return value will have no effect on the original flow.
CompositeDisposable composite = new CompositeDisposable();
#Override
protected void onStop() {
composite.clear();
super.onStop();
}
private void initAzimuthUpdater() {
Disposable d = Observable.interval(500, TimeUnit.MILLISECONDS)
.flatMap(new Function<Long, ObservableSource<Float>>() {
#Override
public ObservableSource<Float> apply(#NonNull Long aLong)
throws Exception {
return Observable.create(new ObservableOnSubscribe<Float>() {
#Override
public void subscribe(#NonNull ObservableEmitter<Float> e)
throws Exception {
e.onNext(someMethod());
}
});
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableObserver<Float>() {
#Override
public void onStart() {
Log.d(TAG, "xxxxxxxx onSubscribe:" + System.currentTimeMillis());
isRunning = true;
}
#Override
public void onNext(#NonNull Float o) {
Log.d(TAG, "xxxxxxxx onNext:" + System.currentTimeMillis());
//update UI
}
#Override
public void onError(#NonNull Throwable e) {
Log.d(TAG, "xxxxxxxx onError:" + System.currentTimeMillis());
}
#Override
public void onComplete() {
Log.d(TAG, "xxxxxxxx onComplete:" + System.currentTimeMillis());
}
});
composite.add(d);
}