提交 ce787ed5 编写于 作者: W Warren Smith 提交者: Jake Wharton

Add support for creating failed test call instances with any exception.

上级 5c2f505a
......@@ -42,7 +42,20 @@ public final class Calls {
return new FakeCall<>(response, null);
}
/** Creates a failed {@link Call} from {@code failure}. */
public static <T> Call<T> failure(IOException failure) {
// TODO delete this overload in Retrofit 3.0.
return new FakeCall<>(null, failure);
}
/**
* Creates a failed {@link Call} from {@code failure}.
* <p>
* Note: When invoking {@link Call#execute() execute()} on the returned {@link Call}, if
* {@code failure} is a {@link RuntimeException}, {@link Error}, or {@link IOException} subtype
* it is thrown directly. Otherwise it is "sneaky thrown" despite not being declared.
*/
public static <T> Call<T> failure(Throwable failure) {
return new FakeCall<>(null, failure);
}
......@@ -52,11 +65,11 @@ public final class Calls {
static final class FakeCall<T> implements Call<T> {
private final Response<T> response;
private final IOException error;
private final Throwable error;
private final AtomicBoolean canceled = new AtomicBoolean();
private final AtomicBoolean executed = new AtomicBoolean();
FakeCall(@Nullable Response<T> response, @Nullable IOException error) {
FakeCall(@Nullable Response<T> response, @Nullable Throwable error) {
if ((response == null) == (error == null)) {
throw new AssertionError("Only one of response or error can be set.");
}
......@@ -74,7 +87,12 @@ public final class Calls {
if (response != null) {
return response;
}
throw error;
throw FakeCall.<Error>sneakyThrow2(error);
}
@SuppressWarnings("unchecked") // Intentionally abusing this feature.
private static <T extends Throwable> T sneakyThrow2(Throwable t) throws T {
throw (T) t;
}
@SuppressWarnings("ConstantConditions") // Guarding public API nullability.
......@@ -131,10 +149,8 @@ public final class Calls {
if (delegate == null) {
try {
delegate = callable.call();
} catch (IOException e) {
delegate = failure(e);
} catch (Exception e) {
throw new IllegalStateException("Callable threw unrecoverable exception", e);
delegate = failure(e);
}
this.delegate = delegate;
}
......
......@@ -15,13 +15,16 @@
*/
package retrofit2.mock;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.Test;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
......@@ -155,6 +158,19 @@ public final class CallsTest {
assertTrue(taco.isExecuted());
}
@Test public void failureExecuteCheckedException() {
CertificateException failure = new CertificateException("Hey");
Call<Object> taco = Calls.failure(failure);
assertFalse(taco.isExecuted());
try {
taco.execute();
fail();
} catch (Throwable e) {
assertSame(failure, e);
}
assertTrue(taco.isExecuted());
}
@Test public void failureEnqueue() {
IOException failure = new IOException("Hey");
Call<Object> taco = Calls.failure(failure);
......@@ -260,4 +276,19 @@ public final class CallsTest {
});
assertSame(failure, failureRef.get());
}
@Test public void deferredThrowUncheckedExceptionEnqueue() {
final RuntimeException failure = new RuntimeException("Hey");
final AtomicReference<Throwable> failureRef = new AtomicReference<>();
Calls.failure(failure).enqueue(new Callback<Object>() {
@Override public void onResponse(Call<Object> call, Response<Object> response) {
fail();
}
@Override public void onFailure(Call<Object> call, Throwable t) {
failureRef.set(t);
}
});
assertSame(failure, failureRef.get());
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册