MockRetrofitTest.java 9.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * Copyright (C) 2013 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
16

J
Jake Wharton 已提交
17
package retrofit2.mock;
18 19 20

import java.io.IOException;
import java.io.InterruptedIOException;
21
import java.util.Random;
22 23 24 25 26 27
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.Before;
import org.junit.Test;
J
Jake Wharton 已提交
28 29 30 31
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
32 33 34 35 36 37 38

import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

39 40 41 42
public final class MockRetrofitTest {
  interface DoWorkService {
    Call<String> response();
    Call<String> failure();
43 44
  }

45
  private final IOException mockFailure = new IOException("Timeout!");
46
  private final NetworkBehavior behavior = NetworkBehavior.create(new Random(2847));
47
  private DoWorkService service;
48

49
  @Before public void setUp() {
50
    Retrofit retrofit = new Retrofit.Builder()
51 52
        .baseUrl("http://example.com")
        .build();
53

54 55 56 57
    MockRetrofit mockRetrofit = MockRetrofit.create(retrofit, behavior);
    final BehaviorDelegate<DoWorkService> delegate = mockRetrofit.create(DoWorkService.class);

    service = new DoWorkService() {
58
      @Override public Call<String> response() {
59 60
        Call<String> response = Calls.response("Response!");
        return delegate.returning(response).response();
61 62
      }

63
      @Override public Call<String> failure() {
64 65
        Call<String> failure = Calls.failure(mockFailure);
        return delegate.returning(failure).failure();
66
      }
67
    };
68 69
  }

70 71 72 73
  @Test public void syncFailureThrowsAfterDelay() {
    behavior.setDelay(100, MILLISECONDS);
    behavior.setVariancePercent(0);
    behavior.setFailurePercent(100);
74

75
    Call<String> call = service.response();
76

77
    long startNanos = System.nanoTime();
78 79 80 81
    try {
      call.execute();
      fail();
    } catch (IOException e) {
82 83 84
      long tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNanos);
      assertThat(e).isSameAs(behavior.failureException());
      assertThat(tookMs).isGreaterThanOrEqualTo(100);
85 86 87
    }
  }

88 89 90 91
  @Test public void asyncFailureTriggersFailureAfterDelay() throws InterruptedException {
    behavior.setDelay(100, MILLISECONDS);
    behavior.setVariancePercent(0);
    behavior.setFailurePercent(100);
92

93
    Call<String> call = service.response();
94

95 96
    final long startNanos = System.nanoTime();
    final AtomicLong tookMs = new AtomicLong();
97 98 99
    final AtomicReference<Throwable> failureRef = new AtomicReference<>();
    final CountDownLatch latch = new CountDownLatch(1);
    call.enqueue(new Callback<String>() {
100
      @Override public void onResponse(Response<String> response) {
101 102 103 104
        throw new AssertionError();
      }

      @Override public void onFailure(Throwable t) {
105
        tookMs.set(TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNanos));
106 107 108 109 110 111
        failureRef.set(t);
        latch.countDown();
      }
    });
    assertTrue(latch.await(1, SECONDS));

112 113
    assertThat(failureRef.get()).isSameAs(behavior.failureException());
    assertThat(tookMs.get()).isGreaterThanOrEqualTo(100);
114 115 116
  }

  @Test public void syncSuccessReturnsAfterDelay() throws IOException {
117 118 119
    behavior.setDelay(100, MILLISECONDS);
    behavior.setVariancePercent(0);
    behavior.setFailurePercent(0);
120

121
    Call<String> call = service.response();
122 123 124 125 126

    long startNanos = System.nanoTime();
    Response<String> response = call.execute();
    long tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNanos);

127
    assertThat(response.body()).isEqualTo("Response!");
128 129 130
    assertThat(tookMs).isGreaterThanOrEqualTo(100);
  }

131 132 133 134
  @Test public void asyncSuccessCalledAfterDelay() throws InterruptedException, IOException {
    behavior.setDelay(100, MILLISECONDS);
    behavior.setVariancePercent(0);
    behavior.setFailurePercent(0);
135

136
    Call<String> call = service.response();
137 138 139

    final long startNanos = System.nanoTime();
    final AtomicLong tookMs = new AtomicLong();
140
    final AtomicReference<String> actual = new AtomicReference<>();
141 142
    final CountDownLatch latch = new CountDownLatch(1);
    call.enqueue(new Callback<String>() {
143
      @Override public void onResponse(Response<String> response) {
144 145 146 147 148 149 150 151 152 153 154
        tookMs.set(TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNanos));
        actual.set(response.body());
        latch.countDown();
      }

      @Override public void onFailure(Throwable t) {
        throw new AssertionError();
      }
    });
    assertTrue(latch.await(1, SECONDS));

155
    assertThat(actual.get()).isEqualTo("Response!");
156 157 158 159
    assertThat(tookMs.get()).isGreaterThanOrEqualTo(100);
  }

  @Test public void syncFailureThrownAfterDelay() {
160 161 162
    behavior.setDelay(100, MILLISECONDS);
    behavior.setVariancePercent(0);
    behavior.setFailurePercent(0);
163

164
    Call<String> call = service.failure();
165 166 167 168 169 170 171 172

    long startNanos = System.nanoTime();
    try {
      call.execute();
      fail();
    } catch (IOException e) {
      long tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNanos);
      assertThat(tookMs).isGreaterThanOrEqualTo(100);
173
      assertThat(e).isSameAs(mockFailure);
174 175 176 177
    }
  }

  @Test public void asyncFailureCalledAfterDelay() throws InterruptedException {
178 179 180
    behavior.setDelay(100, MILLISECONDS);
    behavior.setVariancePercent(0);
    behavior.setFailurePercent(0);
181

182
    Call<String> call = service.failure();
183 184 185 186 187

    final AtomicLong tookMs = new AtomicLong();
    final AtomicReference<Throwable> failureRef = new AtomicReference<>();
    final CountDownLatch latch = new CountDownLatch(1);
    final long startNanos = System.nanoTime();
188
    call.enqueue(new Callback<String>() {
189
      @Override public void onResponse(Response<String> response) {
190 191 192 193 194 195 196 197 198 199 200 201
        throw new AssertionError();
      }

      @Override public void onFailure(Throwable t) {
        tookMs.set(TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNanos));
        failureRef.set(t);
        latch.countDown();
      }
    });
    assertTrue(latch.await(1, SECONDS));

    assertThat(tookMs.get()).isGreaterThanOrEqualTo(100);
202
    assertThat(failureRef.get()).isSameAs(mockFailure);
203 204 205
  }

  @Test public void syncCanBeCanceled() throws IOException {
206 207 208
    behavior.setDelay(10, SECONDS);
    behavior.setVariancePercent(0);
    behavior.setFailurePercent(0);
209

210
    final Call<String> call = service.response();
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229

    new Thread(new Runnable() {
      @Override public void run() {
        try {
          Thread.sleep(100);
          call.cancel();
        } catch (InterruptedException ignored) {
        }
      }
    }).start();

    try {
      call.execute();
      fail();
    } catch (InterruptedIOException e) {
      assertThat(e).hasMessage("canceled");
    }
  }

230 231 232 233 234 235 236 237 238 239
  @Test public void asyncCanBeCanceled() throws InterruptedException {
    behavior.setDelay(10, SECONDS);
    behavior.setVariancePercent(0);
    behavior.setFailurePercent(0);

    final Call<String> call = service.response();

    final AtomicReference<Throwable> failureRef = new AtomicReference<>();
    final CountDownLatch latch = new CountDownLatch(1);
    call.enqueue(new Callback<String>() {
240
      @Override public void onResponse(Response<String> response) {
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
        latch.countDown();
      }

      @Override public void onFailure(Throwable t) {
        failureRef.set(t);
        latch.countDown();
      }
    });

    // TODO we shouldn't need to sleep
    Thread.sleep(100); // Ensure the task has started.
    call.cancel();

    assertTrue(latch.await(1, SECONDS));
    assertThat(failureRef.get()).isInstanceOf(InterruptedIOException.class).hasMessage("canceled");
  }

258
  @Test public void syncCanceledBeforeStart() throws IOException {
259 260 261
    behavior.setDelay(100, MILLISECONDS);
    behavior.setVariancePercent(0);
    behavior.setFailurePercent(0);
262

263
    final Call<String> call = service.response();
264 265 266 267 268 269 270 271 272 273

    call.cancel();
    try {
      call.execute();
      fail();
    } catch (InterruptedIOException e) {
      assertThat(e).hasMessage("canceled");
    }
  }

274 275 276 277
  @Test public void asyncCanBeCanceledBeforeStart() throws InterruptedException {
    behavior.setDelay(10, SECONDS);
    behavior.setVariancePercent(0);
    behavior.setFailurePercent(0);
278

279 280
    final Call<String> call = service.response();
    call.cancel();
281 282 283 284

    final AtomicReference<Throwable> failureRef = new AtomicReference<>();
    final CountDownLatch latch = new CountDownLatch(1);
    call.enqueue(new Callback<String>() {
285
      @Override public void onResponse(Response<String> response) {
286 287 288 289 290 291 292 293 294 295 296 297 298
        latch.countDown();
      }

      @Override public void onFailure(Throwable t) {
        failureRef.set(t);
        latch.countDown();
      }
    });

    assertTrue(latch.await(1, SECONDS));
    assertThat(failureRef.get()).isInstanceOf(InterruptedIOException.class).hasMessage("canceled");
  }
}