### Question:
StreamContext implements Context { @Override public final void addReceiptData(final ByteString data) throws InternalError { TpReceiptAddDataRequest addDataRequest = TpReceiptAddDataRequest.newBuilder().setContextId(contextId).setData(data) .build(); Future future = stream.send(Message.MessageType.TP_RECEIPT_ADD_DATA_REQUEST, addDataRequest.toByteString()); TpReceiptAddDataResponse addDataResponse = null; try { addDataResponse = TpReceiptAddDataResponse.parseFrom(future.getResult(TIME_OUT)); } catch (InterruptedException iee) { throw new InternalError(iee.toString()); } catch (InvalidProtocolBufferException ipbe) { throw new InternalError(ipbe.toString()); } catch (ValidatorConnectionError vce) { throw new InternalError(vce.toString()); } catch (Exception e) { throw new InternalError(e.toString()); } if (addDataResponse != null) { if (addDataResponse.getStatus() == TpReceiptAddDataResponse.Status.ERROR) { throw new InternalError(String.format("Failed to add receipt data %s", data)); } } } StreamContext(final Stream myStream, final String myContextId); @Override final Map<String, ByteString> getState(final Collection<String> addresses); @Override final Collection<String> setState(final Collection<java.util.Map.Entry<String, ByteString>> addressValuePairs); @Override final Collection<String> deleteState(final Collection<String> addresses); @Override final void addReceiptData(final ByteString data); @Override final void addEvent(final String eventType, final Collection<Entry<String, String>> attributes,
      final ByteString data);  }### Answer:
@Test public void testAddReceiptData() { Stream stream = mock(Stream.class); Context ctx = new StreamContext(stream, "test-context-id"); Map<String, String> testMap = new HashMap<>(); testMap.put("testKey1", "testValue1"); testMap.put("testKey2", "testValue2"); ByteString bs = ByteString.copyFromUtf8("testData"); FutureByteString okResponse = new FutureByteString("test-correlation-id"); okResponse.setResult( TpReceiptAddDataResponse.newBuilder().setStatus(TpReceiptAddDataResponse.Status.OK).build().toByteString()); FutureByteString errResponse = new FutureByteString("test-correlation-id"); errResponse.setResult( TpReceiptAddDataResponse.newBuilder().setStatus(TpReceiptAddDataResponse.Status.ERROR).build().toByteString()); FutureByteString garbageResponse = new FutureByteString("test-correlation-id"); garbageResponse.setResult(ByteString.copyFrom("something-garbage-like".getBytes())); try { when(stream.send(any(), any())).thenReturn(okResponse); ctx.addReceiptData(bs); } catch (InternalError exc) { fail("Happy path should not generate an InternalError"); } try { when(stream.send(any(), any())).thenReturn(garbageResponse); ctx.addReceiptData(bs); fail("An error should have been thrown since we responded with something wrong!"); } catch (InternalError ie) { } try { when(stream.send(any(), any())).thenReturn(errResponse); ctx.addReceiptData(bs); fail("An error should have been thrown since we responded with something wrong!"); } catch (InternalError ie) { } }