Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separated Android test code from source. #749

Merged
merged 1 commit into from
Jan 14, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,6 @@
*/
package rx.android.observables;

import static org.mockito.Mockito.verify;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import rx.Observable;
import rx.Observer;
import rx.operators.OperationObserveFromAndroidComponent;
Expand Down Expand Up @@ -108,52 +98,4 @@ public static <T> Observable<T> fromFragment(Object fragment, Observable<T> sour
throw new IllegalArgumentException("Target fragment is neither a native nor support library Fragment");
}
}

@RunWith(RobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public static final class AndroidObservableTest {

// support library fragments
private FragmentActivity fragmentActivity;
private android.support.v4.app.Fragment supportFragment;

// native fragments
private Activity activity;
private Fragment fragment;

@Mock
private Observer<String> observer;

@Before
public void setup() {
MockitoAnnotations.initMocks(this);
supportFragment = new android.support.v4.app.Fragment();
fragmentActivity = Robolectric.buildActivity(FragmentActivity.class).create().get();
fragmentActivity.getSupportFragmentManager().beginTransaction().add(supportFragment, null).commit();

fragment = new Fragment();
activity = Robolectric.buildActivity(Activity.class).create().get();
activity.getFragmentManager().beginTransaction().add(fragment, null).commit();
}

@Test
public void itSupportsFragmentsFromTheSupportV4Library() {
fromFragment(supportFragment, Observable.just("success")).subscribe(observer);
verify(observer).onNext("success");
verify(observer).onCompleted();
}

@Test
public void itSupportsNativeFragments() {
fromFragment(fragment, Observable.just("success")).subscribe(observer);
verify(observer).onNext("success");
verify(observer).onCompleted();
}

@Test(expected = IllegalArgumentException.class)
public void itThrowsIfObjectPassedIsNotAFragment() {
fromFragment("not a fragment", Observable.never());
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,13 @@

import android.os.Handler;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;

import rx.Scheduler;
import rx.Subscription;
import rx.operators.SafeObservableSubscription;
import rx.util.functions.Func2;

import java.util.concurrent.TimeUnit;

import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

/**
* Schedules actions to run on an Android Handler thread.
*/
Expand Down Expand Up @@ -84,49 +74,6 @@ public void run() {
}, unit.toMillis(delayTime));
return subscription;
}

@RunWith(RobolectricTestRunner.class)
@Config(manifest=Config.NONE)
public static final class UnitTest {

@Test
public void shouldScheduleImmediateActionOnHandlerThread() {
final Handler handler = mock(Handler.class);
final Object state = new Object();
@SuppressWarnings("unchecked")
final Func2<Scheduler, Object, Subscription> action = mock(Func2.class);

Scheduler scheduler = new HandlerThreadScheduler(handler);
scheduler.schedule(state, action);

// verify that we post to the given Handler
ArgumentCaptor<Runnable> runnable = ArgumentCaptor.forClass(Runnable.class);
verify(handler).postDelayed(runnable.capture(), eq(0L));

// verify that the given handler delegates to our action
runnable.getValue().run();
verify(action).call(scheduler, state);
}

@Test
public void shouldScheduleDelayedActionOnHandlerThread() {
final Handler handler = mock(Handler.class);
final Object state = new Object();
@SuppressWarnings("unchecked")
final Func2<Scheduler, Object, Subscription> action = mock(Func2.class);

Scheduler scheduler = new HandlerThreadScheduler(handler);
scheduler.schedule(state, action, 1L, TimeUnit.SECONDS);

// verify that we post to the given Handler
ArgumentCaptor<Runnable> runnable = ArgumentCaptor.forClass(Runnable.class);
verify(handler).postDelayed(runnable.capture(), eq(1000L));

// verify that the given handler delegates to our action
runnable.getValue().run();
verify(action).call(scheduler, state);
}
}
}


Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,6 @@
*/
package rx.operators;

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;

import rx.Observable;
import rx.Observer;
import rx.Subscription;
Expand All @@ -42,7 +25,6 @@
import android.os.Looper;
import android.util.Log;

import java.lang.reflect.Field;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
Expand Down Expand Up @@ -164,150 +146,4 @@ protected boolean isComponentValid(android.support.v4.app.Fragment fragment) {
return fragment.isAdded();
}
}

@RunWith(RobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public static final class UnitTest {

@Mock
private Observer<Integer> mockObserver;

@Mock
private Fragment mockFragment;

@Mock
private Activity mockActivity;

@Mock
private Observable<Integer> mockObservable;

@Before
public void setupMocks() {
MockitoAnnotations.initMocks(this);
when(mockFragment.isAdded()).thenReturn(true);
}

@Test
public void itThrowsIfObserverSubscribesFromBackgroundThread() throws Exception {
final Future<Object> future = Executors.newSingleThreadExecutor().submit(new Callable<Object>() {
@Override
public Object call() throws Exception {
OperationObserveFromAndroidComponent.observeFromAndroidComponent(
mockObservable, mockFragment).subscribe(mockObserver);
return null;
}
});
future.get(1, TimeUnit.SECONDS);
verify(mockObserver).onError(any(IllegalStateException.class));
verifyNoMoreInteractions(mockObserver);
}

@Test
public void itObservesTheSourceSequenceOnTheMainUIThread() {
OperationObserveFromAndroidComponent.observeFromAndroidComponent(mockObservable, mockFragment).subscribe(mockObserver);
verify(mockObservable).observeOn(AndroidSchedulers.mainThread());
}

@Test
public void itForwardsOnNextOnCompletedSequenceToTargetObserver() {
Observable<Integer> source = Observable.from(1, 2, 3);
OperationObserveFromAndroidComponent.observeFromAndroidComponent(source, mockFragment).subscribe(mockObserver);
verify(mockObserver, times(3)).onNext(anyInt());
verify(mockObserver).onCompleted();
verify(mockObserver, never()).onError(any(Exception.class));
}

@Test
public void itForwardsOnErrorToTargetObserver() {
final Exception exception = new Exception();
Observable<Integer> source = Observable.error(exception);
OperationObserveFromAndroidComponent.observeFromAndroidComponent(source, mockFragment).subscribe(mockObserver);
verify(mockObserver).onError(exception);
verify(mockObserver, never()).onNext(anyInt());
verify(mockObserver, never()).onCompleted();
}

@Test
public void itDropsOnNextOnCompletedSequenceIfTargetComponentIsGone() throws Throwable {
PublishSubject<Integer> source = PublishSubject.create();

final OnSubscribeFragment<Integer> operator = new OnSubscribeFragment<Integer>(source, mockFragment);
operator.onSubscribe(mockObserver);

source.onNext(1);
releaseComponentRef(operator);

source.onNext(2);
source.onNext(3);
source.onCompleted();

verify(mockObserver).onNext(1);
verifyNoMoreInteractions(mockObserver);
}

@Test
public void itDropsOnErrorIfTargetComponentIsGone() throws Throwable {
PublishSubject<Integer> source = PublishSubject.create();

final OnSubscribeFragment<Integer> operator = new OnSubscribeFragment<Integer>(source, mockFragment);
operator.onSubscribe(mockObserver);

source.onNext(1);
releaseComponentRef(operator);

source.onError(new Exception());

verify(mockObserver).onNext(1);
verifyNoMoreInteractions(mockObserver);
}

private void releaseComponentRef(OnSubscribeFragment<Integer> operator) throws NoSuchFieldException, IllegalAccessException {
final Field componentRef = operator.getClass().getSuperclass().getDeclaredField("componentRef");
componentRef.setAccessible(true);
componentRef.set(operator, null);
}

@Test
public void itDoesNotForwardOnNextOnCompletedSequenceIfFragmentIsDetached() {
PublishSubject<Integer> source = PublishSubject.create();
OperationObserveFromAndroidComponent.observeFromAndroidComponent(source, mockFragment).subscribe(mockObserver);

source.onNext(1);

when(mockFragment.isAdded()).thenReturn(false);
source.onNext(2);
source.onNext(3);
source.onCompleted();

verify(mockObserver).onNext(1);
verify(mockObserver, never()).onCompleted();
}

@Test
public void itDoesNotForwardOnErrorIfFragmentIsDetached() {
PublishSubject<Integer> source = PublishSubject.create();
OperationObserveFromAndroidComponent.observeFromAndroidComponent(source, mockFragment).subscribe(mockObserver);

source.onNext(1);

when(mockFragment.isAdded()).thenReturn(false);
source.onError(new Exception());

verify(mockObserver).onNext(1);
verify(mockObserver, never()).onError(any(Exception.class));
}

@Test
public void itUnsubscribesFromTheSourceSequence() {
Subscription underlying = mock(Subscription.class);
when(mockObservable.observeOn(AndroidSchedulers.mainThread())).thenReturn(mockObservable);
when(mockObservable.subscribe(any(Observer.class))).thenReturn(underlying);

Subscription sub = OperationObserveFromAndroidComponent.observeFromAndroidComponent(
mockObservable, mockActivity).subscribe(mockObserver);
sub.unsubscribe();

verify(underlying).unsubscribe();
}
}
}
Loading