Skip to content

Commit aaa21c1

Browse files
authored
Merge pull request #202 from android10/generic-use-cases
Generic use cases
2 parents 70eeacf + 8c78f8f commit aaa21c1

File tree

14 files changed

+71
-218
lines changed

14 files changed

+71
-218
lines changed

data/src/test/java/com/fernandocejas/android10/sample/data/repository/UserDataRepositoryTest.java

+1-8
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@
2424
import java.util.ArrayList;
2525
import java.util.List;
2626
import org.junit.Before;
27-
import org.junit.Rule;
2827
import org.junit.Test;
29-
import org.junit.rules.ExpectedException;
3028
import org.junit.runner.RunWith;
3129
import org.mockito.Mock;
3230
import org.mockito.runners.MockitoJUnitRunner;
@@ -48,14 +46,9 @@ public class UserDataRepositoryTest {
4846
@Mock private UserEntity mockUserEntity;
4947
@Mock private User mockUser;
5048

51-
@Rule
52-
public ExpectedException expectedException = ExpectedException.none();
53-
5449
@Before
5550
public void setUp() {
56-
userDataRepository = new UserDataRepository(mockUserDataStoreFactory,
57-
mockUserEntityDataMapper);
58-
51+
userDataRepository = new UserDataRepository(mockUserDataStoreFactory, mockUserEntityDataMapper);
5952
given(mockUserDataStoreFactory.create(anyInt())).willReturn(mockUserDataStore);
6053
given(mockUserDataStoreFactory.createCloudDataStore()).willReturn(mockUserDataStore);
6154
}

domain/src/main/java/com/fernandocejas/android10/sample/domain/interactor/GetUserDetails.java

+18-16
Original file line numberDiff line numberDiff line change
@@ -19,38 +19,40 @@
1919
import com.fernandocejas.android10.sample.domain.executor.PostExecutionThread;
2020
import com.fernandocejas.android10.sample.domain.executor.ThreadExecutor;
2121
import com.fernandocejas.android10.sample.domain.repository.UserRepository;
22-
import com.fernandocejas.arrow.annotations.VisibleForTesting;
23-
import com.fernandocejas.arrow.optional.Optional;
22+
import com.fernandocejas.arrow.checks.Preconditions;
2423
import io.reactivex.Observable;
2524
import javax.inject.Inject;
2625

2726
/**
2827
* This class is an implementation of {@link UseCase} that represents a use case for
2928
* retrieving data related to an specific {@link User}.
3029
*/
31-
public class GetUserDetails extends UseCase {
32-
33-
public static final String NAME = "userDetails";
34-
public static final String PARAM_USER_ID_KEY = "userId";
35-
36-
@VisibleForTesting
37-
static final int PARAM_USER_ID_DEFAULT_VALUE = -1;
30+
public class GetUserDetails extends UseCase<User, GetUserDetails.Params> {
3831

3932
private final UserRepository userRepository;
4033

4134
@Inject
42-
public GetUserDetails(UserRepository userRepository, ThreadExecutor threadExecutor,
35+
GetUserDetails(UserRepository userRepository, ThreadExecutor threadExecutor,
4336
PostExecutionThread postExecutionThread) {
4437
super(threadExecutor, postExecutionThread);
4538
this.userRepository = userRepository;
4639
}
4740

48-
@Override protected Observable buildUseCaseObservable(Optional<Params> params) {
49-
if (params.isPresent()) {
50-
final int userId = params.get().getInt(PARAM_USER_ID_KEY, PARAM_USER_ID_DEFAULT_VALUE);
51-
return this.userRepository.user(userId);
52-
} else {
53-
return Observable.empty();
41+
@Override Observable<User> buildUseCaseObservable(Params params) {
42+
Preconditions.checkNotNull(params);
43+
return this.userRepository.user(params.userId);
44+
}
45+
46+
public static final class Params {
47+
48+
private final int userId;
49+
50+
private Params(int userId) {
51+
this.userId = userId;
52+
}
53+
54+
public static Params forUser(int userId) {
55+
return new Params(userId);
5456
}
5557
}
5658
}

domain/src/main/java/com/fernandocejas/android10/sample/domain/interactor/GetUserList.java

+3-5
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,15 @@
1919
import com.fernandocejas.android10.sample.domain.executor.PostExecutionThread;
2020
import com.fernandocejas.android10.sample.domain.executor.ThreadExecutor;
2121
import com.fernandocejas.android10.sample.domain.repository.UserRepository;
22-
import com.fernandocejas.arrow.optional.Optional;
2322
import io.reactivex.Observable;
23+
import java.util.List;
2424
import javax.inject.Inject;
2525

2626
/**
2727
* This class is an implementation of {@link UseCase} that represents a use case for
2828
* retrieving a collection of all {@link User}.
2929
*/
30-
public class GetUserList extends UseCase {
31-
32-
public static final String NAME = "userList";
30+
public class GetUserList extends UseCase<List<User>, Void> {
3331

3432
private final UserRepository userRepository;
3533

@@ -40,7 +38,7 @@ public class GetUserList extends UseCase {
4038
this.userRepository = userRepository;
4139
}
4240

43-
@Override public Observable buildUseCaseObservable(Optional<Params> params) {
41+
@Override Observable<List<User>> buildUseCaseObservable(Void unused) {
4442
return this.userRepository.users();
4543
}
4644
}

domain/src/main/java/com/fernandocejas/android10/sample/domain/interactor/Params.java

-50
This file was deleted.

domain/src/main/java/com/fernandocejas/android10/sample/domain/interactor/UseCase.java

+7-8
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import com.fernandocejas.android10.sample.domain.executor.PostExecutionThread;
1919
import com.fernandocejas.android10.sample.domain.executor.ThreadExecutor;
2020
import com.fernandocejas.arrow.checks.Preconditions;
21-
import com.fernandocejas.arrow.optional.Optional;
2221
import io.reactivex.Observable;
2322
import io.reactivex.disposables.CompositeDisposable;
2423
import io.reactivex.disposables.Disposable;
@@ -33,7 +32,7 @@
3332
* By convention each UseCase implementation will return the result using a {@link DisposableObserver}
3433
* that will execute its job in a background thread and will post the result in the UI thread.
3534
*/
36-
public abstract class UseCase {
35+
public abstract class UseCase<T, Params> {
3736

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

5352
/**
5453
* Executes the current use case.
5554
*
5655
* @param observer {@link DisposableObserver} which will be listening to the observable build
57-
* by {@link #buildUseCaseObservable(Optional)} ()} method.
58-
* @param params Parameters used to build execute this use case.
56+
* by {@link #buildUseCaseObservable(Params)} ()} method.
57+
* @param params Parameters (Optional) used to build/execute this use case.
5958
*/
60-
@SuppressWarnings("unchecked")
61-
public void execute(DisposableObserver observer, Params params) {
62-
final Observable<?> observable = this.buildUseCaseObservable(Optional.of(params))
59+
public void execute(DisposableObserver<T> observer, Params params) {
60+
Preconditions.checkNotNull(observer);
61+
final Observable<T> observable = this.buildUseCaseObservable(params)
6362
.subscribeOn(Schedulers.from(threadExecutor))
6463
.observeOn(postExecutionThread.getScheduler());
6564
addDisposable(observable.subscribeWith(observer));

domain/src/test/java/com/fernandocejas/android10/sample/domain/interactor/GetUserDetailsTest.java

+9-24
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,16 @@
1717

1818
import com.fernandocejas.android10.sample.domain.executor.PostExecutionThread;
1919
import com.fernandocejas.android10.sample.domain.executor.ThreadExecutor;
20+
import com.fernandocejas.android10.sample.domain.interactor.GetUserDetails.Params;
2021
import com.fernandocejas.android10.sample.domain.repository.UserRepository;
21-
import com.fernandocejas.arrow.optional.Optional;
22-
import io.reactivex.Observable;
2322
import org.junit.Before;
23+
import org.junit.Rule;
2424
import org.junit.Test;
25+
import org.junit.rules.ExpectedException;
2526
import org.junit.runner.RunWith;
2627
import org.mockito.Mock;
2728
import org.mockito.runners.MockitoJUnitRunner;
2829

29-
import static org.assertj.core.api.Assertions.assertThat;
3030
import static org.mockito.Mockito.verify;
3131
import static org.mockito.Mockito.verifyNoMoreInteractions;
3232
import static org.mockito.Mockito.verifyZeroInteractions;
@@ -42,6 +42,8 @@ public class GetUserDetailsTest {
4242
@Mock private ThreadExecutor mockThreadExecutor;
4343
@Mock private PostExecutionThread mockPostExecutionThread;
4444

45+
@Rule public ExpectedException expectedException = ExpectedException.none();
46+
4547
@Before
4648
public void setUp() {
4749
getUserDetails = new GetUserDetails(mockUserRepository, mockThreadExecutor,
@@ -50,10 +52,7 @@ public void setUp() {
5052

5153
@Test
5254
public void testGetUserDetailsUseCaseObservableHappyCase() {
53-
final Params params = Params.create();
54-
params.putInt(GetUserDetails.PARAM_USER_ID_KEY, USER_ID);
55-
56-
getUserDetails.buildUseCaseObservable(Optional.of(params));
55+
getUserDetails.buildUseCaseObservable(Params.forUser(USER_ID));
5756

5857
verify(mockUserRepository).user(USER_ID);
5958
verifyNoMoreInteractions(mockUserRepository);
@@ -62,22 +61,8 @@ public void testGetUserDetailsUseCaseObservableHappyCase() {
6261
}
6362

6463
@Test
65-
public void testShouldReturnEmptyObservableWhenNoParameters() {
66-
final Observable observable = getUserDetails.buildUseCaseObservable(Optional.<Params>absent());
67-
68-
assertThat(observable).isEqualTo(Observable.empty());
69-
verifyZeroInteractions(mockUserRepository);
70-
verifyZeroInteractions(mockPostExecutionThread);
71-
verifyZeroInteractions(mockThreadExecutor);
72-
}
73-
74-
@Test
75-
public void testShouldUseDefaultUserIdValueWhenNoUserIdParameter() {
76-
getUserDetails.buildUseCaseObservable(Optional.of(Params.create()));
77-
78-
verify(mockUserRepository).user(GetUserDetails.PARAM_USER_ID_DEFAULT_VALUE);
79-
verifyNoMoreInteractions(mockUserRepository);
80-
verifyZeroInteractions(mockPostExecutionThread);
81-
verifyZeroInteractions(mockThreadExecutor);
64+
public void testShouldFailWhenNoOrEmptyParameters() {
65+
expectedException.expect(NullPointerException.class);
66+
getUserDetails.buildUseCaseObservable(null);
8267
}
8368
}

domain/src/test/java/com/fernandocejas/android10/sample/domain/interactor/GetUserListTest.java

+1-14
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,12 @@
1818
import com.fernandocejas.android10.sample.domain.executor.PostExecutionThread;
1919
import com.fernandocejas.android10.sample.domain.executor.ThreadExecutor;
2020
import com.fernandocejas.android10.sample.domain.repository.UserRepository;
21-
import com.fernandocejas.arrow.optional.Optional;
2221
import org.junit.Before;
2322
import org.junit.Test;
2423
import org.junit.runner.RunWith;
2524
import org.mockito.Mock;
2625
import org.mockito.runners.MockitoJUnitRunner;
2726

28-
import static org.mockito.Mockito.mock;
2927
import static org.mockito.Mockito.verify;
3028
import static org.mockito.Mockito.verifyNoMoreInteractions;
3129
import static org.mockito.Mockito.verifyZeroInteractions;
@@ -47,22 +45,11 @@ public void setUp() {
4745

4846
@Test
4947
public void testGetUserListUseCaseObservableHappyCase() {
50-
getUserList.buildUseCaseObservable(Optional.of(Params.EMPTY));
48+
getUserList.buildUseCaseObservable(null);
5149

5250
verify(mockUserRepository).users();
5351
verifyNoMoreInteractions(mockUserRepository);
5452
verifyZeroInteractions(mockThreadExecutor);
5553
verifyZeroInteractions(mockPostExecutionThread);
5654
}
57-
58-
@Test
59-
@SuppressWarnings("unchecked")
60-
public void testThereShouldNotBeAnyInteractionWithParams() {
61-
Optional params = mock(Optional.class);
62-
63-
getUserList.buildUseCaseObservable(params);
64-
65-
verify(mockUserRepository).users();
66-
verifyZeroInteractions(params);
67-
}
6855
}

domain/src/test/java/com/fernandocejas/android10/sample/domain/interactor/ParamsTest.java

-49
This file was deleted.

0 commit comments

Comments
 (0)