### Question:
RouteGuideClient { public void listFeatures(int lowLat, int lowLon, int hiLat, int hiLon) { info("*** ListFeatures: lowLat={0} lowLon={1} hiLat={2} hiLon={3}", lowLat, lowLon, hiLat, hiLon); Rectangle request = Rectangle.newBuilder() .setLo(Point.newBuilder().setLatitude(lowLat).setLongitude(lowLon).build()) .setHi(Point.newBuilder().setLatitude(hiLat).setLongitude(hiLon).build()).build(); Iterator<Feature> features; try { features = blockingStub.listFeatures(request); for (int i = 1; features.hasNext(); i++) { Feature feature = features.next(); info("Result #" + i + ": {0}", feature); if (testHelper != null) { testHelper.onMessage(feature); } } } catch (StatusRuntimeException e) { warning("RPC failed: {0}", e.getStatus()); if (testHelper != null) { testHelper.onRpcError(e); } } } RouteGuideClient(String host, int port);  RouteGuideClient(ManagedChannelBuilder<?> channelBuilder); void shutdown(); void getFeature(int lat, int lon); void listFeatures(int lowLat, int lowLon, int hiLat, int hiLon); void recordRoute(List<Feature> features, int numPoints); CountDownLatch routeChat(); static void main(String[] args);  }### Answer:
@Test public void listFeatures() { final Feature responseFeature1 = Feature.newBuilder().setName("feature 1").build(); final Feature responseFeature2 = Feature.newBuilder().setName("feature 2").build(); final AtomicReference<Rectangle> rectangleDelivered = new AtomicReference<Rectangle>(); RouteGuideImplBase listFeaturesImpl = new RouteGuideImplBase() { @Override public void listFeatures(Rectangle rectangle, StreamObserver<Feature> responseObserver) { rectangleDelivered.set(rectangle); responseObserver.onNext(responseFeature1); responseObserver.onNext(responseFeature2); responseObserver.onCompleted(); } }; serviceRegistry.addService(listFeaturesImpl); client.listFeatures(1, 2, 3, 4); assertEquals(Rectangle.newBuilder() .setLo(Point.newBuilder().setLatitude(1).setLongitude(2).build()) .setHi(Point.newBuilder().setLatitude(3).setLongitude(4).build()) .build(), rectangleDelivered.get()); verify(testHelper).onMessage(responseFeature1); verify(testHelper).onMessage(responseFeature2); verify(testHelper, never()).onRpcError(any(Throwable.class)); }
@Test public void listFeatures_error() { final Feature responseFeature1 = Feature.newBuilder().setName("feature 1").build(); final AtomicReference<Rectangle> rectangleDelivered = new AtomicReference<Rectangle>(); final StatusRuntimeException fakeError = new StatusRuntimeException(Status.INVALID_ARGUMENT); RouteGuideImplBase listFeaturesImpl = new RouteGuideImplBase() { @Override public void listFeatures(Rectangle rectangle, StreamObserver<Feature> responseObserver) { rectangleDelivered.set(rectangle); responseObserver.onNext(responseFeature1); responseObserver.onError(fakeError); } }; serviceRegistry.addService(listFeaturesImpl); client.listFeatures(1, 2, 3, 4); assertEquals(Rectangle.newBuilder() .setLo(Point.newBuilder().setLatitude(1).setLongitude(2).build()) .setHi(Point.newBuilder().setLatitude(3).setLongitude(4).build()) .build(), rectangleDelivered.get()); ArgumentCaptor<Throwable> errorCaptor = ArgumentCaptor.forClass(Throwable.class); verify(testHelper).onMessage(responseFeature1); verify(testHelper).onRpcError(errorCaptor.capture()); assertEquals(fakeError.getStatus(), Status.fromThrowable(errorCaptor.getValue())); }