@ -1,6 +1,7 @@
@@ -1,6 +1,7 @@
package feign.hystrix ;
import com.netflix.hystrix.HystrixCommand ;
import com.netflix.hystrix.HystrixCommandGroupKey ;
import com.netflix.hystrix.exception.HystrixRuntimeException ;
import com.squareup.okhttp.mockwebserver.MockResponse ;
import com.squareup.okhttp.mockwebserver.MockWebServer ;
@ -10,6 +11,7 @@ import org.junit.Rule;
@@ -10,6 +11,7 @@ import org.junit.Rule;
import org.junit.Test ;
import org.junit.rules.ExpectedException ;
import java.util.ArrayList ;
import java.util.Arrays ;
import java.util.Collections ;
import java.util.List ;
@ -45,6 +47,18 @@ public class HystrixBuilderTest {
@@ -45,6 +47,18 @@ public class HystrixBuilderTest {
assertThat ( command . execute ( ) ) . isEqualTo ( "foo" ) ;
}
@Test
public void hystrixCommandFallback ( ) {
server . enqueue ( new MockResponse ( ) . setResponseCode ( 500 ) ) ;
TestInterface api = target ( ) ;
HystrixCommand < String > command = api . command ( ) ;
assertThat ( command ) . isNotNull ( ) ;
assertThat ( command . execute ( ) ) . isEqualTo ( "fallback" ) ;
}
@Test
public void hystrixCommandInt ( ) {
server . enqueue ( new MockResponse ( ) . setBody ( "1" ) ) ;
@ -57,6 +71,18 @@ public class HystrixBuilderTest {
@@ -57,6 +71,18 @@ public class HystrixBuilderTest {
assertThat ( command . execute ( ) ) . isEqualTo ( new Integer ( 1 ) ) ;
}
@Test
public void hystrixCommandIntFallback ( ) {
server . enqueue ( new MockResponse ( ) . setResponseCode ( 500 ) ) ;
TestInterface api = target ( ) ;
HystrixCommand < Integer > command = api . intCommand ( ) ;
assertThat ( command ) . isNotNull ( ) ;
assertThat ( command . execute ( ) ) . isEqualTo ( new Integer ( 0 ) ) ;
}
@Test
public void hystrixCommandList ( ) {
server . enqueue ( new MockResponse ( ) . setBody ( "[\"foo\",\"bar\"]" ) ) ;
@ -69,12 +95,29 @@ public class HystrixBuilderTest {
@@ -69,12 +95,29 @@ public class HystrixBuilderTest {
assertThat ( command . execute ( ) ) . containsExactly ( "foo" , "bar" ) ;
}
@Test
public void hystrixCommandListFallback ( ) {
server . enqueue ( new MockResponse ( ) . setResponseCode ( 500 ) ) ;
TestInterface api = target ( ) ;
HystrixCommand < List < String > > command = api . listCommand ( ) ;
assertThat ( command ) . isNotNull ( ) ;
assertThat ( command . execute ( ) ) . containsExactly ( "fallback" ) ;
}
// When dealing with fallbacks, it is less tedious to keep interfaces small.
interface GitHub {
@RequestLine ( "GET /repos/{owner}/{repo}/contributors" )
List < String > contributors ( @Param ( "owner" ) String owner , @Param ( "repo" ) String repo ) ;
}
interface GitHubHystrix {
@RequestLine ( "GET /repos/{owner}/{repo}/contributors" )
HystrixCommand < List < String > > contributorsHystrixCommand ( @Param ( "owner" ) String owner , @Param ( "repo" ) String repo ) ;
}
@Test
public void fallbacksApplyOnError ( ) {
server . enqueue ( new MockResponse ( ) . setResponseCode ( 500 ) ) ;
@ -150,6 +193,23 @@ public class HystrixBuilderTest {
@@ -150,6 +193,23 @@ public class HystrixBuilderTest {
Assertions . assertThat ( testSubscriber . getOnNextEvents ( ) . get ( 0 ) ) . isEqualTo ( "foo" ) ;
}
@Test
public void rxObservableFallback ( ) {
server . enqueue ( new MockResponse ( ) . setResponseCode ( 500 ) ) ;
TestInterface api = target ( ) ;
Observable < String > observable = api . observable ( ) ;
assertThat ( observable ) . isNotNull ( ) ;
assertThat ( server . getRequestCount ( ) ) . isEqualTo ( 0 ) ;
TestSubscriber < String > testSubscriber = new TestSubscriber < String > ( ) ;
observable . subscribe ( testSubscriber ) ;
testSubscriber . awaitTerminalEvent ( ) ;
Assertions . assertThat ( testSubscriber . getOnNextEvents ( ) . get ( 0 ) ) . isEqualTo ( "fallback" ) ;
}
@Test
public void rxObservableInt ( ) {
server . enqueue ( new MockResponse ( ) . setBody ( "1" ) ) ;
@ -167,6 +227,23 @@ public class HystrixBuilderTest {
@@ -167,6 +227,23 @@ public class HystrixBuilderTest {
Assertions . assertThat ( testSubscriber . getOnNextEvents ( ) . get ( 0 ) ) . isEqualTo ( new Integer ( 1 ) ) ;
}
@Test
public void rxObservableIntFallback ( ) {
server . enqueue ( new MockResponse ( ) . setResponseCode ( 500 ) ) ;
TestInterface api = target ( ) ;
Observable < Integer > observable = api . intObservable ( ) ;
assertThat ( observable ) . isNotNull ( ) ;
assertThat ( server . getRequestCount ( ) ) . isEqualTo ( 0 ) ;
TestSubscriber < Integer > testSubscriber = new TestSubscriber < Integer > ( ) ;
observable . subscribe ( testSubscriber ) ;
testSubscriber . awaitTerminalEvent ( ) ;
Assertions . assertThat ( testSubscriber . getOnNextEvents ( ) . get ( 0 ) ) . isEqualTo ( new Integer ( 0 ) ) ;
}
@Test
public void rxObservableList ( ) {
server . enqueue ( new MockResponse ( ) . setBody ( "[\"foo\",\"bar\"]" ) ) ;
@ -185,6 +262,24 @@ public class HystrixBuilderTest {
@@ -185,6 +262,24 @@ public class HystrixBuilderTest {
assertThat ( testSubscriber . getOnNextEvents ( ) . get ( 0 ) ) . containsExactly ( "foo" , "bar" ) ;
}
@Test
public void rxObservableListFall ( ) {
server . enqueue ( new MockResponse ( ) . setResponseCode ( 500 ) ) ;
TestInterface api = target ( ) ;
Observable < List < String > > observable = api . listObservable ( ) ;
assertThat ( observable ) . isNotNull ( ) ;
assertThat ( server . getRequestCount ( ) ) . isEqualTo ( 0 ) ;
TestSubscriber < List < String > > testSubscriber = new TestSubscriber < List < String > > ( ) ;
observable . subscribe ( testSubscriber ) ;
testSubscriber . awaitTerminalEvent ( ) ;
assertThat ( testSubscriber . getOnNextEvents ( ) . get ( 0 ) ) . containsExactly ( "fallback" ) ;
}
@Test
public void rxSingle ( ) {
server . enqueue ( new MockResponse ( ) . setBody ( "\"foo\"" ) ) ;
@ -202,6 +297,23 @@ public class HystrixBuilderTest {
@@ -202,6 +297,23 @@ public class HystrixBuilderTest {
Assertions . assertThat ( testSubscriber . getOnNextEvents ( ) . get ( 0 ) ) . isEqualTo ( "foo" ) ;
}
@Test
public void rxSingleFallback ( ) {
server . enqueue ( new MockResponse ( ) . setResponseCode ( 500 ) ) ;
TestInterface api = target ( ) ;
Single < String > single = api . single ( ) ;
assertThat ( single ) . isNotNull ( ) ;
assertThat ( server . getRequestCount ( ) ) . isEqualTo ( 0 ) ;
TestSubscriber < String > testSubscriber = new TestSubscriber < String > ( ) ;
single . subscribe ( testSubscriber ) ;
testSubscriber . awaitTerminalEvent ( ) ;
Assertions . assertThat ( testSubscriber . getOnNextEvents ( ) . get ( 0 ) ) . isEqualTo ( "fallback" ) ;
}
@Test
public void rxSingleInt ( ) {
server . enqueue ( new MockResponse ( ) . setBody ( "1" ) ) ;
@ -219,6 +331,23 @@ public class HystrixBuilderTest {
@@ -219,6 +331,23 @@ public class HystrixBuilderTest {
Assertions . assertThat ( testSubscriber . getOnNextEvents ( ) . get ( 0 ) ) . isEqualTo ( new Integer ( 1 ) ) ;
}
@Test
public void rxSingleIntFallback ( ) {
server . enqueue ( new MockResponse ( ) . setResponseCode ( 500 ) ) ;
TestInterface api = target ( ) ;
Single < Integer > single = api . intSingle ( ) ;
assertThat ( single ) . isNotNull ( ) ;
assertThat ( server . getRequestCount ( ) ) . isEqualTo ( 0 ) ;
TestSubscriber < Integer > testSubscriber = new TestSubscriber < Integer > ( ) ;
single . subscribe ( testSubscriber ) ;
testSubscriber . awaitTerminalEvent ( ) ;
Assertions . assertThat ( testSubscriber . getOnNextEvents ( ) . get ( 0 ) ) . isEqualTo ( new Integer ( 0 ) ) ;
}
@Test
public void rxSingleList ( ) {
server . enqueue ( new MockResponse ( ) . setBody ( "[\"foo\",\"bar\"]" ) ) ;
@ -236,6 +365,23 @@ public class HystrixBuilderTest {
@@ -236,6 +365,23 @@ public class HystrixBuilderTest {
assertThat ( testSubscriber . getOnNextEvents ( ) . get ( 0 ) ) . containsExactly ( "foo" , "bar" ) ;
}
@Test
public void rxSingleListFallback ( ) {
server . enqueue ( new MockResponse ( ) . setResponseCode ( 500 ) ) ;
TestInterface api = target ( ) ;
Single < List < String > > single = api . listSingle ( ) ;
assertThat ( single ) . isNotNull ( ) ;
assertThat ( server . getRequestCount ( ) ) . isEqualTo ( 0 ) ;
TestSubscriber < List < String > > testSubscriber = new TestSubscriber < List < String > > ( ) ;
single . subscribe ( testSubscriber ) ;
testSubscriber . awaitTerminalEvent ( ) ;
assertThat ( testSubscriber . getOnNextEvents ( ) . get ( 0 ) ) . containsExactly ( "fallback" ) ;
}
@Test
public void plainString ( ) {
server . enqueue ( new MockResponse ( ) . setBody ( "\"foo\"" ) ) ;
@ -247,6 +393,17 @@ public class HystrixBuilderTest {
@@ -247,6 +393,17 @@ public class HystrixBuilderTest {
assertThat ( string ) . isEqualTo ( "foo" ) ;
}
@Test
public void plainStringFallback ( ) {
server . enqueue ( new MockResponse ( ) . setResponseCode ( 500 ) ) ;
TestInterface api = target ( ) ;
String string = api . get ( ) ;
assertThat ( string ) . isEqualTo ( "fallback" ) ;
}
@Test
public void plainList ( ) {
server . enqueue ( new MockResponse ( ) . setBody ( "[\"foo\",\"bar\"]" ) ) ;
@ -258,10 +415,21 @@ public class HystrixBuilderTest {
@@ -258,10 +415,21 @@ public class HystrixBuilderTest {
assertThat ( list ) . isNotNull ( ) . containsExactly ( "foo" , "bar" ) ;
}
@Test
public void plainListFallback ( ) {
server . enqueue ( new MockResponse ( ) . setResponseCode ( 500 ) ) ;
TestInterface api = target ( ) ;
List < String > list = api . getList ( ) ;
assertThat ( list ) . isNotNull ( ) . containsExactly ( "fallback" ) ;
}
private TestInterface target ( ) {
return HystrixFeign . builder ( )
. decoder ( new GsonDecoder ( ) )
. target ( TestInterface . class , "http://localhost:" + server . getPort ( ) ) ;
. target ( TestInterface . class , "http://localhost:" + server . getPort ( ) , new FallbackTestInterface ( ) ) ;
}
interface TestInterface {
@ -311,4 +479,71 @@ public class HystrixBuilderTest {
@@ -311,4 +479,71 @@ public class HystrixBuilderTest {
@Headers ( "Accept: application/json" )
List < String > getList ( ) ;
}
class FallbackTestInterface implements TestInterface {
@Override public HystrixCommand < String > command ( ) {
return new HystrixCommand < String > ( HystrixCommandGroupKey . Factory . asKey ( "Test" ) ) {
@Override
protected String run ( ) throws Exception {
return "fallback" ;
}
} ;
}
@Override public HystrixCommand < List < String > > listCommand ( ) {
return new HystrixCommand < List < String > > ( HystrixCommandGroupKey . Factory . asKey ( "Test" ) ) {
@Override protected List < String > run ( ) throws Exception {
List < String > fallbackResult = new ArrayList < String > ( ) ;
fallbackResult . add ( "fallback" ) ;
return fallbackResult ;
}
} ;
}
@Override public HystrixCommand < Integer > intCommand ( ) {
return new HystrixCommand < Integer > ( HystrixCommandGroupKey . Factory . asKey ( "Test" ) ) {
@Override protected Integer run ( ) throws Exception {
return 0 ;
}
} ;
}
@Override public Observable < List < String > > listObservable ( ) {
List < String > fallbackResult = new ArrayList < String > ( ) ;
fallbackResult . add ( "fallback" ) ;
return Observable . just ( fallbackResult ) ;
}
@Override public Observable < String > observable ( ) {
return Observable . just ( "fallback" ) ;
}
@Override public Single < Integer > intSingle ( ) {
return Single . just ( 0 ) ;
}
@Override public Single < List < String > > listSingle ( ) {
List < String > fallbackResult = new ArrayList < String > ( ) ;
fallbackResult . add ( "fallback" ) ;
return Single . just ( fallbackResult ) ;
}
@Override public Single < String > single ( ) {
return Single . just ( "fallback" ) ;
}
@Override public Observable < Integer > intObservable ( ) {
return Observable . just ( 0 ) ;
}
@Override public String get ( ) {
return "fallback" ;
}
@Override public List < String > getList ( ) {
List < String > fallbackResult = new ArrayList < String > ( ) ;
fallbackResult . add ( "fallback" ) ;
return fallbackResult ;
}
}
}