Skip to content

Commit

Permalink
iss1403: added tests for Single and Completable, fixed bugs in Generi…
Browse files Browse the repository at this point in the history
…cObservableCommand related to these RX types
  • Loading branch information
dmgcodevil committed Apr 16, 2017
1 parent 8715b71 commit 67fd60a
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ protected Observable resumeWithFallback() {
Object res = commandActions.getFallbackAction().executeWithArgs(executionType, args);
if (res instanceof Observable) {
return (Observable) res;
} else if (res instanceof Single) {
return ((Single) res).toObservable();
} else if (res instanceof Completable) {
return ((Completable) res).toObservable();
} else {
return Observable.just(res);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import rx.Completable;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
Expand Down Expand Up @@ -92,6 +93,13 @@ public void validateReturnType(Method commandMethod) {
if (ExecutionType.OBSERVABLE == ExecutionType.getExecutionType(commandReturnType)) {
if (ExecutionType.OBSERVABLE != getExecutionType()) {
Type commandParametrizedType = commandMethod.getGenericReturnType();

// basically any object can be wrapped into Completable, Completable itself ins't parametrized
if(Completable.class.isAssignableFrom(commandMethod.getReturnType())) {
validateCompletableReturnType(commandMethod, method.getReturnType());
return;
}

if (isReturnTypeParametrized(commandMethod)) {
commandParametrizedType = getFirstParametrizedType(commandMethod);
}
Expand Down Expand Up @@ -137,6 +145,13 @@ private Type getFirstParametrizedType(Method m) {
return null;
}

// everything can be wrapped into completable except 'void'
private void validateCompletableReturnType(Method commandMethod, Class<?> callbackReturnType) {
if (Void.TYPE == callbackReturnType) {
throw new FallbackDefinitionException(createErrorMsg(commandMethod, method, "fallback cannot return 'void' if command return type is " + Completable.class.getSimpleName()));
}
}

private void validateReturnType(Method commandMethod, Method fallbackMethod) {
if (isGenericReturnType(commandMethod)) {
List<Type> commandParametrizedTypes = flattenTypeVariables(commandMethod.getGenericReturnType());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.slf4j.helpers.MessageFormatter;
import org.springframework.test.context.junit4.rules.SpringClassRule;
import org.springframework.test.context.junit4.rules.SpringMethodRule;
import rx.Completable;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
Expand Down Expand Up @@ -64,6 +65,7 @@ public Object[] methodGenericDefinitionFailure() {
new Object[]{MethodGenericDefinitionFailureCase8.class},
new Object[]{MethodGenericDefinitionFailureCase9.class},
new Object[]{MethodGenericDefinitionFailureCase10.class},
new Object[]{MethodGenericDefinitionFailureCase11.class},

};
}
Expand Down Expand Up @@ -247,6 +249,12 @@ public static class MethodGenericDefinitionFailureCase10 {
private GenericEntity<? super Comparable> fallback() { return null; }
}

public static class MethodGenericDefinitionFailureCase11 {
@HystrixCommand(fallbackMethod = "fallback")
public Completable command() { throw new IllegalStateException(); }
private void fallback() { return; }
}

/* ====================================================================== */
/* ===================== GENERIC CLASS DEFINITIONS =====+================ */
/* =========================== SUCCESS CASES ============================ */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
import rx.Single;
import rx.Subscriber;
import rx.functions.Action1;
import rx.subjects.ReplaySubject;
import rx.functions.Func0;

import static com.netflix.hystrix.contrib.javanica.test.common.CommonUtils.getHystrixCommandByKey;
import static org.junit.Assert.assertEquals;
Expand Down Expand Up @@ -93,19 +93,82 @@ public void call(User user) {
}

@Test
public void testCompletable(){
userService.getUserCompletable("1", "name: ");
com.netflix.hystrix.HystrixInvokableInfo getUserCommand = getHystrixCommandByKey("getUserCompletable");
public void testGetCompletableUser(){
userService.getCompletableUser("1", "name: ");
com.netflix.hystrix.HystrixInvokableInfo getUserCommand = getHystrixCommandByKey("getCompletableUser");
assertTrue(getUserCommand.getExecutionEvents().contains(HystrixEventType.SUCCESS));
}

@Test
public void testSingle(){
userService.getUserSingle("1", "name: ");
com.netflix.hystrix.HystrixInvokableInfo getUserCommand = getHystrixCommandByKey("getUserSingle");
public void testGetCompletableUserWithRegularFallback() {
Completable completable = userService.getCompletableUserWithRegularFallback(null, "name: ");
completable.<User>toObservable().subscribe(new Action1<User>() {
@Override
public void call(User user) {
assertEquals("default_id", user.getId());
}
});
com.netflix.hystrix.HystrixInvokableInfo getUserCommand = getHystrixCommandByKey("getCompletableUserWithRegularFallback");
assertTrue(getUserCommand.getExecutionEvents().contains(HystrixEventType.FAILURE));
assertTrue(getUserCommand.getExecutionEvents().contains(HystrixEventType.FALLBACK_SUCCESS));
}

@Test
public void testGetCompletableUserWithRxFallback() {
Completable completable = userService.getCompletableUserWithRxFallback(null, "name: ");
completable.<User>toObservable().subscribe(new Action1<User>() {
@Override
public void call(User user) {
assertEquals("default_id", user.getId());
}
});
com.netflix.hystrix.HystrixInvokableInfo getUserCommand = getHystrixCommandByKey("getCompletableUserWithRxFallback");
assertTrue(getUserCommand.getExecutionEvents().contains(HystrixEventType.FAILURE));
assertTrue(getUserCommand.getExecutionEvents().contains(HystrixEventType.FALLBACK_SUCCESS));
}

@Test
public void testGetSingleUser() {
final String id = "1";
Single<User> user = userService.getSingleUser(id, "name: ");
user.subscribe(new Action1<User>() {
@Override
public void call(User user) {
assertEquals(id, user.getId());
}
});
com.netflix.hystrix.HystrixInvokableInfo getUserCommand = getHystrixCommandByKey("getSingleUser");
assertTrue(getUserCommand.getExecutionEvents().contains(HystrixEventType.SUCCESS));
}

@Test
public void testGetSingleUserWithRegularFallback(){
Single<User> user = userService.getSingleUserWithRegularFallback(null, "name: ");
user.subscribe(new Action1<User>() {
@Override
public void call(User user) {
assertEquals("default_id", user.getId());
}
});
com.netflix.hystrix.HystrixInvokableInfo getUserCommand = getHystrixCommandByKey("getSingleUserWithRegularFallback");
assertTrue(getUserCommand.getExecutionEvents().contains(HystrixEventType.FAILURE));
assertTrue(getUserCommand.getExecutionEvents().contains(HystrixEventType.FALLBACK_SUCCESS));
}

@Test
public void testGetSingleUserWithRxFallback(){
Single<User> user = userService.getSingleUserWithRxFallback(null, "name: ");
user.subscribe(new Action1<User>() {
@Override
public void call(User user) {
assertEquals("default_id", user.getId());
}
});
com.netflix.hystrix.HystrixInvokableInfo getUserCommand = getHystrixCommandByKey("getSingleUserWithRxFallback");
assertTrue(getUserCommand.getExecutionEvents().contains(HystrixEventType.FAILURE));
assertTrue(getUserCommand.getExecutionEvents().contains(HystrixEventType.FALLBACK_SUCCESS));
}

@Test
public void testGetUserWithRegularFallback() {
final User exUser = new User("def", "def");
Expand Down Expand Up @@ -179,17 +242,58 @@ public Observable<User> getUser(final String id, final String name) {
}

@HystrixCommand
public Completable getUserCompletable(final String id, final String name) {
validate(id, name, "getUser has failed");
public Completable getCompletableUser(final String id, final String name) {
validate(id, name, "getCompletableUser has failed");
return createObservable(id, name).toCompletable();
}

@HystrixCommand(fallbackMethod = "completableUserRegularFallback")
public Completable getCompletableUserWithRegularFallback(final String id, final String name) {
return getCompletableUser(id, name);
}

@HystrixCommand(fallbackMethod = "completableUserRxFallback")
public Completable getCompletableUserWithRxFallback(final String id, final String name) {
return getCompletableUser(id, name);
}

public User completableUserRegularFallback(final String id, final String name) {
return new User("default_id", "default_name");
}

public Completable completableUserRxFallback(final String id, final String name) {
return Completable.fromCallable(new Func0<User>() {
@Override
public User call() {
return new User("default_id", "default_name");
}
});
}

@HystrixCommand
public Single getUserSingle(final String id, final String name) {
validate(id, name, "getUser has failed");
public Single<User> getSingleUser(final String id, final String name) {
validate(id, name, "getSingleUser has failed");
return createObservable(id, name).toSingle();
}

@HystrixCommand(fallbackMethod = "singleUserRegularFallback")
public Single<User> getSingleUserWithRegularFallback(final String id, final String name) {
return getSingleUser(id, name);
}

@HystrixCommand(fallbackMethod = "singleUserRxFallback")
public Single<User> getSingleUserWithRxFallback(final String id, final String name) {
return getSingleUser(id, name);
}

User singleUserRegularFallback(final String id, final String name) {
return new User("default_id", "default_name");
}

Single<User> singleUserRxFallback(final String id, final String name) {
return createObservable("default_id", "default_name").toSingle();
}

@HystrixCommand(fallbackMethod = "regularFallback", observableExecutionMode = ObservableExecutionMode.LAZY)
public Observable<User> getUserRegularFallback(final String id, final String name) {
validate(id, name, "getUser has failed");
Expand Down

0 comments on commit 67fd60a

Please sign in to comment.