### Question:
TimelineFragment extends ControllerPresenterFragment<TimelineView> implements TimelineAdapter.OnItemClickListener,
        BaseFragmentPagerAdapter.Controller { @VisibleForTesting void bindIfNeeded() { if(!hasPresenterView()) { return; } sendShownAnalyticEvent(); if (!hasSubscriptions()) { this.timelineInteractor.updateIfEmpty(); this.stateSafeExecutor.execute(this.presenterView::pulseHeaderView); bindAndSubscribe(this.timelineInteractor.timeline, this::bindTimeline, this::timelineUnavailable); bindAndSubscribe(this.preferences.observableUse24Time(), this.presenterView::setUse24Time, Functions.LOG_ERROR); } else if (this.presenterView.inNoDataState()) { update(); } }  static TimelineFragment newInstance(@NonNull final LocalDate date,
                                               @Nullable final Timeline cachedTimeline); @Override void setVisibleToUser(final boolean isVisible); @Override void initializePresenterView(); @Override void onCreate(final Bundle savedInstanceState); @Override void onViewCreated(final View view, final Bundle savedInstanceState); @Override void onTrimMemory(final int level); @Override void onPause(); @Override void onDestroyView(); @Override void onDetach(); @Override void onActivityResult(final int requestCode, final int resultCode, final Intent data); @Override void onRequestPermissionsResult(final int requestCode, @NonNull final String[] permissions, @NonNull final int[] grantResults); void showTimelineNavigator(@NonNull final LocalDate date,
                                      @Nullable final Timeline timeline); void share(); void showBreakdown(@NonNull final View sender); void dismissVisibleOverlaysAndDialogs(); @SuppressWarnings("ConstantConditions") @NonNull LocalDate getDate(); @Nullable Timeline getCachedTimeline(); void onSwipeBetweenDatesStarted(); void scrollToTop(); void update(); boolean isAtLeastThreeDaysOld(); void bindTimeline(@NonNull final Timeline timeline); void timelineUnavailable(final Throwable e); @Override void onSegmentItemClicked(final int position, final View view, @NonNull final TimelineEvent event); @Override void onEventItemClicked(final int eventPosition, @NonNull final TimelineEvent event); static final int ZOOMED_OUT_TIMELINE_REQUEST; }### Answer:
@Test public void bindIfNeededTest() { spyOnTimelineInteractor(); assertTrue(fragment.hasPresenterView()); fragment.observableContainer.clearSubscriptions(); assertFalse(fragment.hasSubscriptions()); fragment.bindIfNeeded(); fragment.bindIfNeeded(); fragment.bindIfNeeded(); verify(fragment.timelineInteractor).updateIfEmpty(); verify(fragment).bindAndSubscribe(eq(fragment.timelineInteractor.timeline), any(), any()); fragment.presenterView = mock(TimelineView.class); when(fragment.presenterView.inNoDataState()).thenReturn(true); verify(fragment, times(2)).bindAndSubscribe(any(), any(), any()); assertTrue(fragment.hasSubscriptions()); fragment.bindIfNeeded(); fragment.bindIfNeeded(); verify(fragment, times(2)).update(); }