Skip to content

Commit dfd61c2

Browse files
committed
Dynamic parameters in use cases.
1 parent 988e02b commit dfd61c2

File tree

18 files changed

+233
-69
lines changed

18 files changed

+233
-69
lines changed

buildsystem/dependencies.gradle

+4-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ ext {
2222
gsonVersion = '2.3'
2323
okHttpVersion = '2.5.0'
2424
androidAnnotationsVersion = '21.0.3'
25+
arrowVersion = '1.0.0'
2526

2627
//Testing
2728
robolectricVersion = '3.1.1'
@@ -42,7 +43,7 @@ ext {
4243
recyclerView: "com.android.support:recyclerview-v7:${recyclerViewVersion}",
4344
rxJava: "io.reactivex:rxjava:${rxJavaVersion}",
4445
rxAndroid: "io.reactivex:rxandroid:${rxAndroidVersion}",
45-
javaxAnnotation: "javax.annotation:jsr250-api:${javaxAnnotationVersion}",
46+
javaxAnnotation: "javax.annotation:jsr250-api:${javaxAnnotationVersion}"
4647
]
4748

4849
presentationTestDependencies = [
@@ -57,11 +58,13 @@ ext {
5758
javaxAnnotation: "javax.annotation:jsr250-api:${javaxAnnotationVersion}",
5859
javaxInject: "javax.inject:javax.inject:${javaxInjectVersion}",
5960
rxJava: "io.reactivex:rxjava:${rxJavaVersion}",
61+
arrow: "com.fernandocejas:arrow:${arrowVersion}"
6062
]
6163

6264
domainTestDependencies = [
6365
junit: "junit:junit:${jUnitVersion}",
6466
mockito: "org.mockito:mockito-core:${mockitoVersion}",
67+
assertj: "org.assertj:assertj-core:${assertJVersion}"
6568
]
6669

6770
dataDependencies = [

domain/build.gradle

+3-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ dependencies {
2323

2424
compile domainDependencies.javaxInject
2525
compile domainDependencies.rxJava
26+
compile domainDependencies.arrow
2627

2728
testCompile domainTestDependencies.junit
2829
testCompile domainTestDependencies.mockito
29-
}
30+
testCompile domainTestDependencies.assertj
31+
}

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

+15-6
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
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;
2224
import javax.inject.Inject;
2325
import rx.Observable;
2426

@@ -29,19 +31,26 @@
2931
public class GetUserDetails extends UseCase {
3032

3133
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;
3238

33-
private final int userId;
3439
private final UserRepository userRepository;
3540

3641
@Inject
37-
public GetUserDetails(int userId, UserRepository userRepository,
38-
ThreadExecutor threadExecutor, PostExecutionThread postExecutionThread) {
42+
public GetUserDetails(UserRepository userRepository, ThreadExecutor threadExecutor,
43+
PostExecutionThread postExecutionThread) {
3944
super(threadExecutor, postExecutionThread);
40-
this.userId = userId;
4145
this.userRepository = userRepository;
4246
}
4347

44-
@Override protected Observable buildUseCaseObservable() {
45-
return this.userRepository.user(this.userId);
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();
54+
}
4655
}
4756
}

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
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;
2223
import javax.inject.Inject;
2324
import rx.Observable;
2425

@@ -39,7 +40,7 @@ public class GetUserList extends UseCase {
3940
this.userRepository = userRepository;
4041
}
4142

42-
@Override public Observable buildUseCaseObservable() {
43+
@Override public Observable buildUseCaseObservable(Optional<Params> params) {
4344
return this.userRepository.users();
4445
}
4546
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/**
2+
* Copyright (C) 2016 Fernando Cejas Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.fernandocejas.android10.sample.domain.interactor;
17+
18+
import java.util.HashMap;
19+
import java.util.Map;
20+
21+
/**
22+
* Class backed by a Map, used to pass parameters to {@link UseCase} instances.
23+
*/
24+
public final class Params {
25+
public static final Params EMPTY = Params.create();
26+
27+
private final Map<String, Object> parameters = new HashMap<>();
28+
29+
private Params() {}
30+
31+
public static Params create() {
32+
return new Params();
33+
}
34+
35+
public void putInt(String key, int value) {
36+
parameters.put(key, value);
37+
}
38+
39+
int getInt(String key, int defaultValue) {
40+
final Object object = parameters.get(key);
41+
if (object == null) {
42+
return defaultValue;
43+
}
44+
try {
45+
return (int) object;
46+
} catch (ClassCastException e) {
47+
return defaultValue;
48+
}
49+
}
50+
}

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

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

1818
import com.fernandocejas.android10.sample.domain.executor.PostExecutionThread;
1919
import com.fernandocejas.android10.sample.domain.executor.ThreadExecutor;
20-
import rx.Subscriber;
20+
import com.fernandocejas.arrow.optional.Optional;
2121
import rx.Observable;
22+
import rx.Subscriber;
2223
import rx.Subscription;
2324
import rx.schedulers.Schedulers;
2425
import rx.subscriptions.Subscriptions;
@@ -38,26 +39,26 @@ public abstract class UseCase {
3839

3940
private Subscription subscription = Subscriptions.empty();
4041

41-
protected UseCase(ThreadExecutor threadExecutor,
42-
PostExecutionThread postExecutionThread) {
42+
protected UseCase(ThreadExecutor threadExecutor, PostExecutionThread postExecutionThread) {
4343
this.threadExecutor = threadExecutor;
4444
this.postExecutionThread = postExecutionThread;
4545
}
4646

4747
/**
4848
* Builds an {@link rx.Observable} which will be used when executing the current {@link UseCase}.
4949
*/
50-
protected abstract Observable buildUseCaseObservable();
50+
protected abstract Observable buildUseCaseObservable(Optional<Params> params);
5151

5252
/**
5353
* Executes the current use case.
5454
*
55-
* @param useCaseSubscriber The guy who will be listen to the observable build
56-
* with {@link #buildUseCaseObservable()}.
55+
* @param useCaseSubscriber Subscriber which will be listening to the observable build
56+
* by {@link #buildUseCaseObservable(Optional)} ()} method.
57+
* @param params Parameters used to build execute this use case.
5758
*/
5859
@SuppressWarnings("unchecked")
59-
public void execute(Subscriber useCaseSubscriber) {
60-
this.subscription = this.buildUseCaseObservable()
60+
public void execute(Subscriber useCaseSubscriber, Params params) {
61+
this.subscription = this.buildUseCaseObservable(Optional.of(params))
6162
.subscribeOn(Schedulers.from(threadExecutor))
6263
.observeOn(postExecutionThread.getScheduler())
6364
.subscribe(useCaseSubscriber);

domain/src/test/java/com/fernandocejas/android10/sample/domain/UserTest.java

+3-4
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@
1818
import org.junit.Before;
1919
import org.junit.Test;
2020

21-
import static org.hamcrest.core.Is.is;
22-
import static org.junit.Assert.assertThat;
21+
import static org.assertj.core.api.Assertions.assertThat;
2322

2423
public class UserTest {
2524

@@ -34,8 +33,8 @@ public void setUp() {
3433

3534
@Test
3635
public void testUserConstructorHappyCase() {
37-
int userId = user.getUserId();
36+
final int userId = user.getUserId();
3837

39-
assertThat(userId, is(FAKE_USER_ID));
38+
assertThat(userId).isEqualTo(FAKE_USER_ID);
4039
}
4140
}

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

+31-5
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,23 @@
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;
2122
import org.junit.Before;
2223
import org.junit.Test;
2324
import org.junit.runner.RunWith;
2425
import org.mockito.Mock;
2526
import org.mockito.runners.MockitoJUnitRunner;
27+
import rx.Observable;
2628

29+
import static org.assertj.core.api.Assertions.assertThat;
2730
import static org.mockito.Mockito.verify;
2831
import static org.mockito.Mockito.verifyNoMoreInteractions;
2932
import static org.mockito.Mockito.verifyZeroInteractions;
3033

3134
@RunWith(MockitoJUnitRunner.class)
3235
public class GetUserDetailsTest {
3336

34-
private static final int FAKE_USER_ID = 123;
37+
private static final int USER_ID = 123;
3538

3639
private GetUserDetails getUserDetails;
3740

@@ -41,15 +44,38 @@ public class GetUserDetailsTest {
4144

4245
@Before
4346
public void setUp() {
44-
getUserDetails = new GetUserDetails(FAKE_USER_ID, mockUserRepository,
45-
mockThreadExecutor, mockPostExecutionThread);
47+
getUserDetails = new GetUserDetails(mockUserRepository, mockThreadExecutor,
48+
mockPostExecutionThread);
4649
}
4750

4851
@Test
4952
public void testGetUserDetailsUseCaseObservableHappyCase() {
50-
getUserDetails.buildUseCaseObservable();
53+
final Params params = Params.create();
54+
params.putInt(GetUserDetails.PARAM_USER_ID_KEY, USER_ID);
5155

52-
verify(mockUserRepository).user(FAKE_USER_ID);
56+
getUserDetails.buildUseCaseObservable(Optional.of(params));
57+
58+
verify(mockUserRepository).user(USER_ID);
59+
verifyNoMoreInteractions(mockUserRepository);
60+
verifyZeroInteractions(mockPostExecutionThread);
61+
verifyZeroInteractions(mockThreadExecutor);
62+
}
63+
64+
@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);
5379
verifyNoMoreInteractions(mockUserRepository);
5480
verifyZeroInteractions(mockPostExecutionThread);
5581
verifyZeroInteractions(mockThreadExecutor);

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

+14-1
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@
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;
2122
import org.junit.Before;
2223
import org.junit.Test;
2324
import org.junit.runner.RunWith;
2425
import org.mockito.Mock;
2526
import org.mockito.runners.MockitoJUnitRunner;
2627

28+
import static org.mockito.Mockito.mock;
2729
import static org.mockito.Mockito.verify;
2830
import static org.mockito.Mockito.verifyNoMoreInteractions;
2931
import static org.mockito.Mockito.verifyZeroInteractions;
@@ -45,11 +47,22 @@ public void setUp() {
4547

4648
@Test
4749
public void testGetUserListUseCaseObservableHappyCase() {
48-
getUserList.buildUseCaseObservable();
50+
getUserList.buildUseCaseObservable(Optional.of(Params.EMPTY));
4951

5052
verify(mockUserRepository).users();
5153
verifyNoMoreInteractions(mockUserRepository);
5254
verifyZeroInteractions(mockThreadExecutor);
5355
verifyZeroInteractions(mockPostExecutionThread);
5456
}
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+
}
5568
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* Copyright (C) 2016 Fernando Cejas Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.fernandocejas.android10.sample.domain.interactor;
17+
18+
import org.junit.Before;
19+
import org.junit.Test;
20+
import org.junit.runner.RunWith;
21+
import org.mockito.runners.MockitoJUnitRunner;
22+
23+
import static org.assertj.core.api.Assertions.assertThat;
24+
25+
@RunWith(MockitoJUnitRunner.class)
26+
public class ParamsTest {
27+
28+
private Params params;
29+
30+
@Before
31+
public void setUp() {
32+
params = Params.create();
33+
}
34+
35+
@Test
36+
public void testShouldReturnIntValue() {
37+
params.putInt("key01", 3);
38+
39+
assertThat(params.getInt("key01", 5)).isEqualTo(3);
40+
}
41+
42+
@Test
43+
public void testShouldReturnIntDefaultValue() {
44+
params.putInt("key01", 3);
45+
params.putInt("key02", 4);
46+
47+
assertThat(params.getInt("key03", 5)).isEqualTo(5);
48+
}
49+
}

0 commit comments

Comments
 (0)