Last active
October 20, 2016 13:58
-
-
Save justintuchek/90ca2f622879978a1df122bb013c0413 to your computer and use it in GitHub Desktop.
A behavioral transformer for observables! All inspiration from Retrofit's mock network behavior configurations.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public final class BehaviorTransformer { | |
private final Random random = new Random(); | |
private long delayMs = 2000; | |
private int variancePercent = 40; | |
private int errorCode = 1337; | |
private int failurePercent = 3; | |
public <T> Observable.Transformer<T, T> modify() { | |
return new Observable.Transformer<T, T>() { | |
@Override | |
public Observable<T> call(Observable<T> source) { | |
return source.delay(calculateDelay(TimeUnit.MILLISECONDS), TimeUnit.MILLISECONDS) | |
.concatMap(new Func1<T, Observable<T>>() { | |
@Override | |
public Observable<T> call(T t) { | |
if(calculateIsFailure()) { | |
return Observable.error(new EnumeratedException(errorCode, new RuntimeException())); | |
} else { | |
return Observable.just(t); | |
} | |
} | |
}); | |
} | |
}; | |
} | |
public void setDelayMs(long delayMs) { | |
this.delayMs = delayMs; | |
} | |
public void setVariancePercent(int variancePercent) { | |
this.variancePercent = variancePercent; | |
} | |
public void setErrorCode(int errorCode) { | |
this.errorCode = errorCode; | |
} | |
public void setFailurePercent(int failurePercent) { | |
this.failurePercent = failurePercent; | |
} | |
private boolean calculateIsFailure() { | |
int randomValue = random.nextInt(100); | |
return randomValue < failurePercent; | |
} | |
private long calculateDelay(TimeUnit unit) { | |
float delta = variancePercent / 100f; // e.g., 20 / 100f == 0.2f | |
float lowerBound = 1f - delta; // 0.2f --> 0.8f | |
float upperBound = 1f + delta; // 0.2f --> 1.2f | |
float bound = upperBound - lowerBound; // 1.2f - 0.8f == 0.4f | |
float delayPercent = lowerBound + (random.nextFloat() * bound); // 0.8 + (rnd * 0.4) | |
long callDelayMs = (long) (delayMs * delayPercent); | |
return MILLISECONDS.convert(callDelayMs, unit); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class EnumeratedException extends Throwable { | |
private final int errorCode; | |
public EnumeratedException(int errorCode, Throwable cause) { | |
super(cause); | |
this.errorCode = errorCode; | |
} | |
public int getErrorCode() { | |
return errorCode; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class MockUserService { | |
private final BehaviorTransformer behavior; | |
private Boolean isLoggedIn = Boolean.TRUE; | |
public MockUserService(BehaviorTransformer behavior) { | |
this.behavior = behavior; | |
} | |
public Observable<String> getUsername() { | |
return Observable.just("Justin Tuchek").compose(behavior.<String>modify()); | |
} | |
public Observable<Boolean> logout() { | |
return Observable.just(Boolean.TRUE).compose(behavior.<Boolean>modify()) | |
.doOnNext(new Action1<Boolean>() { | |
@Override | |
public void call(Boolean aBoolean) { | |
isLoggedIn = Boolean.FALSE; | |
} | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment