Hi i have created implementation that uses flatmap to chain two requests together with the final outcome being a response object returned from the second request and wondering if it is possible to mock these two chained response objects?
Here is the main code
delegator.requestOne(requestData)
.flatMap ({ response ->
if(response.isSuccessful){
cookieStorage.saveSessionCookies(response.header(cookieStorage.COOKIE_HEADER_NAME)!!)
}
delegator.requestTwo
})
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(object : SingleObserver<ResponseTwo>() {
#Override
fun onSubscribe(Disposable d) {
}
#Override
fun onSuccess(responseTwo :ResponseTwo) {
callback.onSuccess(responseTwo)
}
#Override
public void onError(Throwable e) {
}
});
If this did not have a flatmap and handled just one request/response i would write the below using mockito
Mockito.when(network.makeReq()).thenReturn(Single.just(responseOne));
But how can i do something like this:
Mockito.when(foodHygieneController.getLocalAuthorities()).thenReturn(Single.just(requestOne)).thenReturn(requestTwo)??
assuming requestOne and RequestTwo are hard coded mock values of my choosing
You simply mock every request (call to a mocked object) that is part of your Rx chain.
In your case:
Mockito.when(delegator.requestOne(...)).thenReturn(...)
Mockito.when(delegator.requestTwo(...)).thenReturn(...) / Mockito.when(delegator.requestTwo(responseOne)).thenReturn(...)
You can then test that the 'output' (emitted items) from that chain are what you expect them to be, for example with a TestSubscriber, or in your example, that callback is called with the ResponseTwo you expect / have mocked.
The Rx chain will operate in your test exactly as it does when running the code 'normally'.
What you cannot do is mock the behaviour of the Rx chain, e.g. you cannot mock how flatMap{} operates.
Related
I want to implement method to edit a note, save it to local database (cache) and then send it to the server as a POST request. I am learning RxJava and I wanted to create Observable from the note and then apply transformations on it, like to map it to an Entity model and saving. The issue that my method returns Completable and this chain returns Observable<Completable>. How to unwrap the Completable from this Observable which I used only to start RxJava stuff. Each editNote() methods returns a Completable.
override fun editNote(note: Note): Completable {
return Observable.just(note)
.map { mapper.mapToEntity(it) }
.map { noteEntity ->
factory.getCacheDataStore().editNote(noteEntity)
.andThen { factory.getRemoteDataStore().editNote(noteEntity) }
}
}
=======================================================
UPDATE
Finally, I managed to find "a solution" but I am not sure it is correct :-)
override fun editNote(note: Note): Completable {
return Observable.just(note)
.map { mapper.mapToEntity(it) }
.flatMapCompletable { noteEntity ->
factory.getCacheDataStore().editNote(noteEntity)
.andThen { factory.getRemoteDataStore().editNote(noteEntity) }
}
}
You're looking for flatMapCompletable instead of map, because map just intercepts the stream and maps the emissions to another type, while 'flatMap' (or it's siblings), from the docs:
Transform the items emitted by an Observable into Observables, then flatten the emissions from those into a single Observable.
You can see it's marble diagram in Here
I'm refactoring legacy code and I want to know if code below is more efficient than regular RxJava operators chain?
Observable.just(collection.getItems().asSequence()
.filter { it.itemId == null }
.filter { it.anotherProp == prop }.toList())
Thanks
The number 1 advantage of Rx is asynchronous execution, and threads changing (if you could say like that). If you do not need it, then it is more efficient to use, what you called Kotlin chains, cause every chain (every method call) in the Rx chain creates new observable, for example:
.filter{ ... }
results in this method call, which will create ObservableFilter
#CheckReturnValue
#SchedulerSupport(SchedulerSupport.NONE)
public final Observable<T> filter(Predicate<? super T> predicate) {
ObjectHelper.requireNonNull(predicate, "predicate is null");
return RxJavaPlugins.onAssembly(new ObservableFilter<T>(this, predicate));
}
Kotlin .filter{...} operator on the other hand uses inlined function
public inline fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T> {
return filterTo(ArrayList<T>(), predicate)
}
I would say that, the Rx is best pick if you need to change threads or perform some of chain calls asynchronously, or if whole your system is built upon Rx.
I want to call multiple Rest Api's in a Sequence and having each Response Dto is different from each other.
Please help me to get rid from this situation that, How can i call these Api's using Rx Java Observables in Android.
no, you should use map() or doOnNext(), it will look like this
Observable.just(1)
.doOnNext(value -> {
someRequestX().execute();
})
.map(value -> {
return nextRequestY().execute();
})
.doOnNext(requestYResponse-> {
someRequesZ(requestYResponse.someValue).execute();
})
.map(requestYResponse-> {
return someRequesK(requestYResponse.someValue).execute();
})
.map(requestKResponse -> {
return someRequesJ(requestKResponse.someValue).execute();
})
.subscribe(requestJResponse -> {
doSOmethingWithFinalResponse(requestJResponse );
})
First of all, for network requests is better to use Single then Observable, because there always will be only one item. To switch from one requests to another, you can use flatMap.
Assuming your code is similar, you can try this:
class Dto1 {}
class Dto2 {}
class Dto3 {}
public interface Api {
Single<Dto1> getDto1();
Single<Dto2> getDto2();
Single<Dto3> getDto3();
}
private Api api;
public void callApi() {
api.getDto1()
.doOnSuccess(dto1 -> {/*do something with dto1*/})
.flatMap(dto1 -> api.getDto2())
.doOnSuccess(dto2 -> {/*do something with dto2*/})
.flatMap(dto2 -> api.getDto3())
.doOnSuccess(dto3 -> {/*do something with dto3*/})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe()
}
For the same scenario, i use concat operator which takes multiple Observables and concatenates their sequence
If response sequence doesn't require then you can use merge operator also.
Concat VS Merge operaror
try doOnNext() or map() method of Observable and use sync execute() of each response and pass them further
I'm Really new on this but What I'm trying to do is
Do two call on parallel both are objects, then I need create a new object using the properties of both
This is a pseudo example that I need
OperatorINeed(service.callOne(), service.callTwo())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.concatMap(new BiFunction<ObjectA, ObjectB, ObjectC>() {
public ObjectC apply(ObjectA objectA, ObjectB objectB) {
// do things
return objectC;
}
})
onErrorResumeNext(...)
but I can't find any concrete example of this thing
use zip() operator, it will collect both emissions from the two service Observables that will run in parraell, and there you provide the BiFunction to map both Objects properties to a new single Object, afterwards you can apply concatMap() with objectC :
Observable.zip(service.callOne(), service.callTwo(),
new BiFunction<ObjectA, ObjectB, ObjectC>() {
#Override
public ObjectC apply(ObjectA objectA, ObjectB objectB) throws Exception {
// do things
return objectC;
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.concatMap(objectC -> { //create an Observable using objectC})
.onErrorResumeNext(...)
I've found nice example of usage RxJava at this article:
Subscription subscription = Single.create(new Single.OnSubscribe() {
#Override
public void call(SingleSubscriber singleSubscriber) {
String value = longRunningOperation();
singleSubscriber.onSuccess(value);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1() {
#Override
public void call(String value) {
// onSuccess
Snackbar.make(rootView, value, Snackbar.LENGTH_LONG).show();
}
}, new Action1() {
#Override
public void call(Throwable throwable) {
// handle onError
}
});
But since I am using Retrofit I would like to create RetrofitService and use Single class to combine the result of two requests to backend into one dataset, as described:
When subscribing to a Single, there is only an onSuccess Action and an
onError action. The Single class has a different set of operators than
Observable, with several operators that allow for a mechanism of
converting a Single to an Observable. For example, using the
Single.mergeWith() operator, two or more Singles of the same type can
be merged together to create an Observable, emitting the results of
each Single to one Observable.
Is it possible to achieve this (and how)?
Yes, see Retrofit Adapters
Only worked with Retrofit2.0