11/**
22 * Copyright 2013 Netflix, Inc.
3- *
3+ *
44 * Licensed under the Apache License, Version 2.0 (the "License");
55 * you may not use this file except in compliance with the License.
66 * You may obtain a copy of the License at
7- *
8- * http://www.apache.org/licenses/LICENSE-2.0
9- *
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
1010 * Unless required by applicable law or agreed to in writing, software
1111 * distributed under the License is distributed on an "AS IS" BASIS,
1212 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313 * See the License for the specific language governing permissions and
1414 * limitations under the License.
1515 */
16- package rx .operators ;
16+ package rx .android . operators ;
1717
18- import static org .mockito .Matchers .any ;
19- import static org .mockito .Matchers .anyInt ;
20- import static org .mockito .Mockito .mock ;
21- import static org .mockito .Mockito .never ;
22- import static org .mockito .Mockito .times ;
23- import static org .mockito .Mockito .verify ;
24- import static org .mockito .Mockito .verifyNoMoreInteractions ;
25- import static org .mockito .Mockito .when ;
18+ import static org .junit .Assert .*;
19+ import static org .mockito .Matchers .*;
20+ import static org .mockito .Mockito .*;
21+
22+ import java .lang .reflect .Constructor ;
23+ import java .lang .reflect .Field ;
24+ import java .lang .reflect .InvocationTargetException ;
25+ import java .util .concurrent .Callable ;
26+ import java .util .concurrent .Executors ;
27+ import java .util .concurrent .Future ;
28+ import java .util .concurrent .TimeUnit ;
29+ import java .util .concurrent .atomic .AtomicReference ;
2630
2731import org .junit .Before ;
32+ import org .junit .Ignore ;
2833import org .junit .Test ;
2934import org .junit .runner .RunWith ;
30- import static org .junit .Assert .*;
3135import org .mockito .Mock ;
3236import org .mockito .MockitoAnnotations ;
3337import org .robolectric .RobolectricTestRunner ;
3438import org .robolectric .annotation .Config ;
3539
3640import rx .Observable ;
41+ import rx .Observable .OnSubscribeFunc ;
3742import rx .Observer ;
3843import rx .Subscription ;
3944import rx .android .schedulers .AndroidSchedulers ;
45+ import rx .operators .OperationObserveFromAndroidComponent ;
46+ import rx .schedulers .Schedulers ;
4047import rx .subjects .PublishSubject ;
48+ import rx .subscriptions .BooleanSubscription ;
49+ import rx .util .functions .Action1 ;
4150import android .app .Activity ;
4251import android .app .Fragment ;
43- import android .os .Looper ;
44- import android .util .Log ;
45-
46- import java .lang .reflect .Field ;
47- import java .lang .reflect .Constructor ;
48- import java .lang .reflect .InvocationTargetException ;
49- import java .util .concurrent .Callable ;
50- import java .util .concurrent .Executors ;
51- import java .util .concurrent .Future ;
52- import java .util .concurrent .TimeUnit ;
5352
5453@ RunWith (RobolectricTestRunner .class )
5554@ Config (manifest = Config .NONE )
@@ -64,9 +63,6 @@ public class OperationObserveFromAndroidComponentTest {
6463 @ Mock
6564 private Activity mockActivity ;
6665
67- @ Mock
68- private Observable <Integer > mockObservable ;
69-
7066 @ Before
7167 public void setupMocks () {
7268 MockitoAnnotations .initMocks (this );
@@ -75,11 +71,12 @@ public void setupMocks() {
7571
7672 @ Test
7773 public void itThrowsIfObserverSubscribesFromBackgroundThread () throws Exception {
74+ final Observable <Integer > testObservable = Observable .from (1 );
7875 final Future <Object > future = Executors .newSingleThreadExecutor ().submit (new Callable <Object >() {
7976 @ Override
8077 public Object call () throws Exception {
8178 OperationObserveFromAndroidComponent .observeFromAndroidComponent (
82- mockObservable , mockFragment ).subscribe (mockObserver );
79+ testObservable , mockFragment ).subscribe (mockObserver );
8380 return null ;
8481 }
8582 });
@@ -88,10 +85,44 @@ public Object call() throws Exception {
8885 verifyNoMoreInteractions (mockObserver );
8986 }
9087
91- @ Test
88+ // TODO needs to be fixed, see comments inline below
89+ @ Ignore
9290 public void itObservesTheSourceSequenceOnTheMainUIThread () {
93- OperationObserveFromAndroidComponent .observeFromAndroidComponent (mockObservable , mockFragment ).subscribe (mockObserver );
94- verify (mockObservable ).observeOn (AndroidSchedulers .mainThread ());
91+ final Observable <Integer > testObservable = Observable .from (1 )
92+ .observeOn (Schedulers .newThread ())
93+ .doOnNext (new Action1 <Integer >() {
94+
95+ @ Override
96+ public void call (Integer t1 ) {
97+ System .out .println ("threadA: " + Thread .currentThread ());
98+ }
99+ })
100+ .observeOn (AndroidSchedulers .mainThread ())
101+ .doOnNext (new Action1 <Integer >() {
102+
103+ @ Override
104+ public void call (Integer t1 ) {
105+ System .out .println ("threadB: " + Thread .currentThread ());
106+ }
107+ });
108+
109+ final AtomicReference <String > currentThreadName = new AtomicReference <String >();
110+ OperationObserveFromAndroidComponent .observeFromAndroidComponent (testObservable , mockFragment ).subscribe (new Action1 <Integer >() {
111+
112+ @ Override
113+ public void call (Integer i ) {
114+ System .out .println ("threadV: " + Thread .currentThread ());
115+ currentThreadName .set (Thread .currentThread ().getName ());
116+ }
117+ });
118+
119+ assertEquals ("androidMainThreadName???" , currentThreadName .get ());
120+
121+ //TODO Can't use Mockito to validate Observable.observeOn as it is now marked as final.
122+ // I can't figure out what to validate about the AndroidSchedulers.mainThread()
123+ // as the code above doesn't print `threadB` so I can't see what Thread it should be.
124+ // I was going to run it on NewThread then observeOn to AndroidThread and validate it jumped
125+ // to the correct thread, but it doesn't do anything. Need to work with Android devs.
95126 }
96127
97128 @ Test
@@ -147,7 +178,7 @@ public void itDropsOnErrorIfTargetComponentIsGone() throws Throwable {
147178 verifyNoMoreInteractions (mockObserver );
148179 }
149180
150- private Observable .OnSubscribeFunc <Integer > newOnSubscribeFragmentInstance (Observable <Integer > source , Fragment fragment ) throws NoSuchMethodException , IllegalAccessException , InstantiationException , InvocationTargetException {
181+ private Observable .OnSubscribeFunc <Integer > newOnSubscribeFragmentInstance (Observable <Integer > source , Fragment fragment ) throws NoSuchMethodException , IllegalAccessException , InstantiationException , InvocationTargetException {
151182 final Class [] klasses = OperationObserveFromAndroidComponent .class .getDeclaredClasses ();
152183 Class onSubscribeFragmentClass = null ;
153184 for (Class klass : klasses ) {
@@ -200,14 +231,23 @@ public void itDoesNotForwardOnErrorIfFragmentIsDetached() {
200231
201232 @ Test
202233 public void itUnsubscribesFromTheSourceSequence () {
203- Subscription underlying = mock (Subscription .class );
204- when (mockObservable .observeOn (AndroidSchedulers .mainThread ())).thenReturn (mockObservable );
205- when (mockObservable .subscribe (any (Observer .class ))).thenReturn (underlying );
234+ final BooleanSubscription s = new BooleanSubscription ();
235+ Observable <Integer > testObservable = Observable .create (new OnSubscribeFunc <Integer >() {
236+
237+ @ Override
238+ public Subscription onSubscribe (Observer <? super Integer > o ) {
239+ o .onNext (1 );
240+ o .onCompleted ();
241+ return s ;
242+ }
243+
244+ });
206245
207246 Subscription sub = OperationObserveFromAndroidComponent .observeFromAndroidComponent (
208- mockObservable , mockActivity ).subscribe (mockObserver );
247+ testObservable , mockActivity ).subscribe (mockObserver );
209248 sub .unsubscribe ();
210249
211- verify ( underlying ). unsubscribe ( );
250+ assertTrue ( s . isUnsubscribed () );
212251 }
252+
213253}
0 commit comments