public static <InputT, OutputT> DoFnInvoker<InputT, OutputT> invokerFor(
      DoFn<InputT, OutputT> fn) {
    return ByteBuddyDoFnInvokerFactory.only().newByteBuddyInvoker(fn);
  }
@Test
  public void testTruncateFnWithHasDefaultMethodsWhenUnbounded() throws Exception {
    class UnboundedMockFn extends DoFn<String, String> {
      @ProcessElement
      public void processElement(
          ProcessContext c,
          RestrictionTracker<RestrictionWithUnboundedDefaultTracker, Void> tracker,
          WatermarkEstimator<WatermarkEstimatorStateWithDefaultWatermarkEstimator>
              watermarkEstimator) {}

      @GetInitialRestriction
      public RestrictionWithUnboundedDefaultTracker getInitialRestriction(@Element String element) {
        return null;
      }

      @GetInitialWatermarkEstimatorState
      public WatermarkEstimatorStateWithDefaultWatermarkEstimator
          getInitialWatermarkEstimatorState() {
        return null;
      }
    }

    UnboundedMockFn fn = mock(UnboundedMockFn.class);
    DoFnInvoker<String, String> invoker = DoFnInvokers.invokerFor(fn);

    CoderRegistry coderRegistry = CoderRegistry.createDefault();
    coderRegistry.registerCoderProvider(
        CoderProviders.fromStaticMethods(
            RestrictionWithUnboundedDefaultTracker.class, CoderForDefaultTracker.class));
    coderRegistry.registerCoderForClass(
        WatermarkEstimatorStateWithDefaultWatermarkEstimator.class,
        new CoderForWatermarkEstimatorStateWithDefaultWatermarkEstimator());
    assertThat(
        invoker.<RestrictionWithBoundedDefaultTracker>invokeGetRestrictionCoder(coderRegistry),
        instanceOf(CoderForDefaultTracker.class));
    assertThat(
        invoker.invokeGetWatermarkEstimatorStateCoder(coderRegistry),
        instanceOf(CoderForWatermarkEstimatorStateWithDefaultWatermarkEstimator.class));
    RestrictionTracker tracker =
        invoker.invokeNewTracker(
            new FakeArgumentProvider<String, String>() {
              @Override
              public Object restriction() {
                return new RestrictionWithUnboundedDefaultTracker();
              }
            });
    assertThat(tracker, instanceOf(UnboundedDefaultTracker.class));
    TruncateResult<?> result =
        invoker.invokeTruncateRestriction(
            new FakeArgumentProvider<String, String>() {
              @Override
              public RestrictionTracker restrictionTracker() {
                return tracker;
              }

              @Override
              public String element(DoFn<String, String> doFn) {
                return "blah";
              }

              @Override
              public Object restriction() {
                return "foo";
              }
            });
    assertNull(result);
    assertEquals(stop(), invoker.invokeProcessElement(mockArgumentProvider));
    assertThat(
        invoker.invokeNewWatermarkEstimator(
            new FakeArgumentProvider<String, String>() {
              @Override
              public Object watermarkEstimatorState() {
                return new WatermarkEstimatorStateWithDefaultWatermarkEstimator();
              }
            }),
        instanceOf(DefaultWatermarkEstimator.class));
  }