Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #202 from android10/generic-use-cases
Generic use cases
  • Loading branch information
android10 committed Dec 27, 2016
2 parents 70eeacf + 8c78f8f commit aaa21c1
Show file tree
Hide file tree
Showing 14 changed files with 71 additions and 218 deletions.
Expand Up @@ -24,9 +24,7 @@
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
Expand All @@ -48,14 +46,9 @@ public class UserDataRepositoryTest {
@Mock private UserEntity mockUserEntity;
@Mock private User mockUser;

@Rule
public ExpectedException expectedException = ExpectedException.none();

@Before
public void setUp() {
userDataRepository = new UserDataRepository(mockUserDataStoreFactory,
mockUserEntityDataMapper);

userDataRepository = new UserDataRepository(mockUserDataStoreFactory, mockUserEntityDataMapper);
given(mockUserDataStoreFactory.create(anyInt())).willReturn(mockUserDataStore);
given(mockUserDataStoreFactory.createCloudDataStore()).willReturn(mockUserDataStore);
}
Expand Down
Expand Up @@ -19,38 +19,40 @@
import com.fernandocejas.android10.sample.domain.executor.PostExecutionThread;
import com.fernandocejas.android10.sample.domain.executor.ThreadExecutor;
import com.fernandocejas.android10.sample.domain.repository.UserRepository;
import com.fernandocejas.arrow.annotations.VisibleForTesting;
import com.fernandocejas.arrow.optional.Optional;
import com.fernandocejas.arrow.checks.Preconditions;
import io.reactivex.Observable;
import javax.inject.Inject;

/**
* This class is an implementation of {@link UseCase} that represents a use case for
* retrieving data related to an specific {@link User}.
*/
public class GetUserDetails extends UseCase {

public static final String NAME = "userDetails";
public static final String PARAM_USER_ID_KEY = "userId";

@VisibleForTesting
static final int PARAM_USER_ID_DEFAULT_VALUE = -1;
public class GetUserDetails extends UseCase<User, GetUserDetails.Params> {

private final UserRepository userRepository;

@Inject
public GetUserDetails(UserRepository userRepository, ThreadExecutor threadExecutor,
GetUserDetails(UserRepository userRepository, ThreadExecutor threadExecutor,
PostExecutionThread postExecutionThread) {
super(threadExecutor, postExecutionThread);
this.userRepository = userRepository;
}

@Override protected Observable buildUseCaseObservable(Optional<Params> params) {
if (params.isPresent()) {
final int userId = params.get().getInt(PARAM_USER_ID_KEY, PARAM_USER_ID_DEFAULT_VALUE);
return this.userRepository.user(userId);
} else {
return Observable.empty();
@Override Observable<User> buildUseCaseObservable(Params params) {
Preconditions.checkNotNull(params);
return this.userRepository.user(params.userId);
}

public static final class Params {

private final int userId;

private Params(int userId) {
this.userId = userId;
}

public static Params forUser(int userId) {
return new Params(userId);
}
}
}
Expand Up @@ -19,17 +19,15 @@
import com.fernandocejas.android10.sample.domain.executor.PostExecutionThread;
import com.fernandocejas.android10.sample.domain.executor.ThreadExecutor;
import com.fernandocejas.android10.sample.domain.repository.UserRepository;
import com.fernandocejas.arrow.optional.Optional;
import io.reactivex.Observable;
import java.util.List;
import javax.inject.Inject;

/**
* This class is an implementation of {@link UseCase} that represents a use case for
* retrieving a collection of all {@link User}.
*/
public class GetUserList extends UseCase {

public static final String NAME = "userList";
public class GetUserList extends UseCase<List<User>, Void> {

private final UserRepository userRepository;

Expand All @@ -40,7 +38,7 @@ public class GetUserList extends UseCase {
this.userRepository = userRepository;
}

@Override public Observable buildUseCaseObservable(Optional<Params> params) {
@Override Observable<List<User>> buildUseCaseObservable(Void unused) {
return this.userRepository.users();
}
}

This file was deleted.

Expand Up @@ -18,7 +18,6 @@
import com.fernandocejas.android10.sample.domain.executor.PostExecutionThread;
import com.fernandocejas.android10.sample.domain.executor.ThreadExecutor;
import com.fernandocejas.arrow.checks.Preconditions;
import com.fernandocejas.arrow.optional.Optional;
import io.reactivex.Observable;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
Expand All @@ -33,7 +32,7 @@
* By convention each UseCase implementation will return the result using a {@link DisposableObserver}
* that will execute its job in a background thread and will post the result in the UI thread.
*/
public abstract class UseCase {
public abstract class UseCase<T, Params> {

private final ThreadExecutor threadExecutor;
private final PostExecutionThread postExecutionThread;
Expand All @@ -48,18 +47,18 @@ public abstract class UseCase {
/**
* Builds an {@link Observable} which will be used when executing the current {@link UseCase}.
*/
protected abstract Observable buildUseCaseObservable(Optional<Params> params);
abstract Observable<T> buildUseCaseObservable(Params params);

/**
* Executes the current use case.
*
* @param observer {@link DisposableObserver} which will be listening to the observable build
* by {@link #buildUseCaseObservable(Optional)} ()} method.
* @param params Parameters used to build execute this use case.
* by {@link #buildUseCaseObservable(Params)} ()} method.
* @param params Parameters (Optional) used to build/execute this use case.
*/
@SuppressWarnings("unchecked")
public void execute(DisposableObserver observer, Params params) {
final Observable<?> observable = this.buildUseCaseObservable(Optional.of(params))
public void execute(DisposableObserver<T> observer, Params params) {
Preconditions.checkNotNull(observer);
final Observable<T> observable = this.buildUseCaseObservable(params)
.subscribeOn(Schedulers.from(threadExecutor))
.observeOn(postExecutionThread.getScheduler());
addDisposable(observable.subscribeWith(observer));
Expand Down
Expand Up @@ -17,16 +17,16 @@

import com.fernandocejas.android10.sample.domain.executor.PostExecutionThread;
import com.fernandocejas.android10.sample.domain.executor.ThreadExecutor;
import com.fernandocejas.android10.sample.domain.interactor.GetUserDetails.Params;
import com.fernandocejas.android10.sample.domain.repository.UserRepository;
import com.fernandocejas.arrow.optional.Optional;
import io.reactivex.Observable;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
Expand All @@ -42,6 +42,8 @@ public class GetUserDetailsTest {
@Mock private ThreadExecutor mockThreadExecutor;
@Mock private PostExecutionThread mockPostExecutionThread;

@Rule public ExpectedException expectedException = ExpectedException.none();

@Before
public void setUp() {
getUserDetails = new GetUserDetails(mockUserRepository, mockThreadExecutor,
Expand All @@ -50,10 +52,7 @@ public void setUp() {

@Test
public void testGetUserDetailsUseCaseObservableHappyCase() {
final Params params = Params.create();
params.putInt(GetUserDetails.PARAM_USER_ID_KEY, USER_ID);

getUserDetails.buildUseCaseObservable(Optional.of(params));
getUserDetails.buildUseCaseObservable(Params.forUser(USER_ID));

verify(mockUserRepository).user(USER_ID);
verifyNoMoreInteractions(mockUserRepository);
Expand All @@ -62,22 +61,8 @@ public void testGetUserDetailsUseCaseObservableHappyCase() {
}

@Test
public void testShouldReturnEmptyObservableWhenNoParameters() {
final Observable observable = getUserDetails.buildUseCaseObservable(Optional.<Params>absent());

assertThat(observable).isEqualTo(Observable.empty());
verifyZeroInteractions(mockUserRepository);
verifyZeroInteractions(mockPostExecutionThread);
verifyZeroInteractions(mockThreadExecutor);
}

@Test
public void testShouldUseDefaultUserIdValueWhenNoUserIdParameter() {
getUserDetails.buildUseCaseObservable(Optional.of(Params.create()));

verify(mockUserRepository).user(GetUserDetails.PARAM_USER_ID_DEFAULT_VALUE);
verifyNoMoreInteractions(mockUserRepository);
verifyZeroInteractions(mockPostExecutionThread);
verifyZeroInteractions(mockThreadExecutor);
public void testShouldFailWhenNoOrEmptyParameters() {
expectedException.expect(NullPointerException.class);
getUserDetails.buildUseCaseObservable(null);
}
}
Expand Up @@ -18,14 +18,12 @@
import com.fernandocejas.android10.sample.domain.executor.PostExecutionThread;
import com.fernandocejas.android10.sample.domain.executor.ThreadExecutor;
import com.fernandocejas.android10.sample.domain.repository.UserRepository;
import com.fernandocejas.arrow.optional.Optional;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
Expand All @@ -47,22 +45,11 @@ public void setUp() {

@Test
public void testGetUserListUseCaseObservableHappyCase() {
getUserList.buildUseCaseObservable(Optional.of(Params.EMPTY));
getUserList.buildUseCaseObservable(null);

verify(mockUserRepository).users();
verifyNoMoreInteractions(mockUserRepository);
verifyZeroInteractions(mockThreadExecutor);
verifyZeroInteractions(mockPostExecutionThread);
}

@Test
@SuppressWarnings("unchecked")
public void testThereShouldNotBeAnyInteractionWithParams() {
Optional params = mock(Optional.class);

getUserList.buildUseCaseObservable(params);

verify(mockUserRepository).users();
verifyZeroInteractions(params);
}
}

This file was deleted.

0 comments on commit aaa21c1

Please sign in to comment.