### Question:
RateLimiterClient { public Single<Boolean> isRateLimited(RateLimit limit) { return getRateLimits() .switchIfEmpty(Maybe.just(RateLimitProto.RateLimit.getDefaultInstance())) .map(storedLimits -> storedLimits.getLimitsOrDefault(limit.limiterKey(), newCounter())) .filter(counter -> isLimitExpired(counter, limit) || counter.getValue() < limit.limit()) .isEmpty(); } @Inject  RateLimiterClient(
      @com.google.firebase.inappmessaging.internal.injection.qualifiers.RateLimit
          ProtoStorageClient storageClient,
      Clock clock); Completable increment(RateLimit limit); Single<Boolean> isRateLimited(RateLimit limit);  }### Answer:
@Test public void increment_readErrors_notifiesError() { when(storageClient.read(any(RateLimitParser.class))).thenReturn(Maybe.error(new IOException())); TestObserver<Boolean> testObserver = rateLimiterClient.isRateLimited(rateLimit).test(); testObserver.assertError(IOException.class); }
@Test public void isRateLimited_ifExpired_isFalse() { RateLimit noTTLLimit = RateLimit.builder() .setLimit(LIMIT_TWO) .setLimiterKey(LIMITER_KEY) .setTimeToLiveMillis(0L) .build(); TestObserver<Boolean> testObserver = rateLimiterClient.isRateLimited(noTTLLimit).test(); assertThat(testObserver.getEvents().get(0)).containsExactly(false); }
@Test public void isRateLimited_ifNoLimits_isFalse() { when(storageClient.read(any(RateLimitParser.class))).thenReturn(Maybe.empty()); RateLimit oneLimit = RateLimit.builder().setLimit(1).setLimiterKey(LIMITER_KEY).setTimeToLiveMillis(TTL).build(); TestObserver<Boolean> testObserver = rateLimiterClient.isRateLimited(oneLimit).test(); assertThat(testObserver.getEvents().get(0)).containsExactly(false); }
@Test public void isRateLimited_readError_notifiesError() { when(storageClient.read(any(RateLimitParser.class))).thenReturn(Maybe.error(new IOException())); TestObserver<Boolean> testObserver = rateLimiterClient.isRateLimited(rateLimit).test(); testObserver.assertError(IOException.class); }