Skip to content

Generic use cases #202

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

Merged
merged 2 commits into from
Dec 27, 2016
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 @@ -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
Original file line number Diff line number Diff line change
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);
}
}
}
Original file line number Diff line number Diff line change
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.

Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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);
}
}
Original file line number Diff line number Diff line change
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.

Loading