/* * Copyright 2015 Jacek Marchwicki <jacek.marchwicki@gmail.com> * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.appunite.rx.simpletests; import com.appunite.rx.ObservableExtensions; import com.appunite.rx.operators.OnSubscribeRefCountDelayed; import com.appunite.rx.operators.OperatorCounter; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.concurrent.TimeUnit; import javax.annotation.Nonnull; import rx.Observable; import rx.Observer; import rx.Subscription; import rx.functions.Func1; import rx.functions.Func2; import rx.schedulers.TestScheduler; import rx.subjects.PublishSubject; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyZeroInteractions; @SuppressWarnings("unchecked") public class NotificationObservableTest { @Mock Observer<? super User> userObserver1; @Mock Observer<? super User> userObserver2; @Mock Observer<? super Integer> mIntegerObserver; private Observable<User> userObservable; private PublishSubject<Object> incrementSubject; private PublishSubject<User> apiResponse; private TestScheduler scheduler; static class User { @Nonnull private final String name; private final long commentsCount; User(@Nonnull final String name, final long commentsCount) { this.name = name; this.commentsCount = commentsCount; } public static User create(@Nonnull final String name, final long commentsCount) { return new User(name, commentsCount); } @Nonnull public String name() { return name; } public long commentsCount() { return commentsCount; } public User increemtnComments(int count) { return new User(name, commentsCount + count); } @Override public boolean equals(final Object o) { if (this == o) return true; if (!(o instanceof User)) return false; final User user = (User) o; return commentsCount == user.commentsCount && name.equals(user.name); } @Override public int hashCode() { int result = name.hashCode(); result = 31 * result + (int) (commentsCount ^ (commentsCount >>> 32)); return result; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", commentsCount=" + commentsCount + '}'; } } @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); scheduler = new TestScheduler(); apiResponse = PublishSubject.create(); incrementSubject = PublishSubject.create(); final Observable<Integer> incrementationCounter = incrementSubject.lift(OperatorCounter.create()); final Observable<User> userFromApiWithIncrement = apiResponse .flatMap(new Func1<User, Observable<User>>() { @Override public Observable<User> call(final User user) { return Observable.combineLatest(Observable.just(user), incrementationCounter, new Func2<User, Integer, User>() { @Override public User call(final User user, final Integer integer) { return user.increemtnComments(integer); } }); } }); userObservable = OnSubscribeRefCountDelayed.create(userFromApiWithIncrement.replay(1), 5, TimeUnit.SECONDS, scheduler); } @Test public void testSubscribeBeforeTimeout() throws Exception { final Subscription subscribe = userObservable.subscribe(userObserver1); apiResponse.onNext(User.create("franek", 10)); subscribe.unsubscribe(); scheduler.advanceTimeBy(1, TimeUnit.SECONDS); userObservable.subscribe(userObserver2); verify(userObserver2).onNext(User.create("franek", 10)); verifyNoMoreInteractions(userObserver2); } @Test public void testSubscribeAfterTimeout() throws Exception { final Subscription subscribe = userObservable.subscribe(userObserver1); apiResponse.onNext(User.create("franek", 10)); subscribe.unsubscribe(); scheduler.advanceTimeBy(5, TimeUnit.SECONDS); userObservable.subscribe(userObserver2); verifyZeroInteractions(userObserver2); } @Test public void testTwoConcurrentSubscription() throws Exception { userObservable.subscribe(userObserver1); userObservable.subscribe(userObserver2); apiResponse.onNext(User.create("franek", 10)); verify(userObserver1).onNext(User.create("franek", 10)); verify(userObserver2).onNext(User.create("franek", 10)); } @Test public void testOnSecondSubscription_returnsOnlyOnce() throws Exception { userObservable.subscribe(userObserver1); apiResponse.onNext(User.create("franek", 10)); apiResponse.onNext(User.create("zenek", 10)); verify(userObserver1).onNext(User.create("franek", 10)); verify(userObserver1).onNext(User.create("zenek", 10)); verifyNoMoreInteractions(userObserver1); userObservable.subscribe(userObserver2); verify(userObserver2).onNext(User.create("zenek", 10)); verifyNoMoreInteractions(userObserver2); } @Test public void testTwoSequentSubscription() throws Exception { userObservable.subscribe(userObserver1).unsubscribe(); apiResponse.onNext(User.create("zenek", 10)); scheduler.advanceTimeBy(5, TimeUnit.SECONDS); userObservable.subscribe(userObserver2); apiResponse.onNext(User.create("franek", 10)); verifyZeroInteractions(userObserver1); verify(userObserver2).onNext(User.create("franek", 10)); verifyNoMoreInteractions(userObserver2); } @Test public void testIncrementAfterApiResponse() throws Exception { userObservable.subscribe(userObserver1); apiResponse.onNext(User.create("franek", 10)); incrementSubject.onNext(null); verify(userObserver1).onNext(User.create("franek", 10)); verify(userObserver1).onNext(User.create("franek", 11)); verifyNoMoreInteractions(userObserver1); } @Test public void testIncrementBeforeSubscription() throws Exception { incrementSubject.onNext(null); userObservable.subscribe(userObserver1); apiResponse.onNext(User.create("franek", 10)); verify(userObserver1).onNext(User.create("franek", 10)); verifyNoMoreInteractions(userObserver1); } @Test public void testIncrementBeforeResponseAfterSubscription() throws Exception { userObservable.subscribe(userObserver1); incrementSubject.onNext(null); apiResponse.onNext(User.create("franek", 10)); verify(userObserver1).onNext(User.create("franek", 10)); verifyNoMoreInteractions(userObserver1); } @Test public void testApiRefresh_counterIsOverridenByApi() throws Exception { userObservable.subscribe(userObserver1); apiResponse.onNext(User.create("franek", 10)); incrementSubject.onNext(null); incrementSubject.onNext(null); reset(userObserver1); apiResponse.onNext(User.create("zenek", 20)); verify(userObserver1).onNext(User.create("zenek", 20)); verifyNoMoreInteractions(userObserver1); } }