### Question:
IbftBlockHeightManager implements BlockHeightManager { @Override public void handleRoundChangePayload(final RoundChange message) { final ConsensusRoundIdentifier targetRound = message.getRoundIdentifier(); LOG.trace("Received a RoundChange Payload for {}", targetRound); final MessageAge messageAge = determineAgeOfPayload(message.getRoundIdentifier().getRoundNumber()); if (messageAge == PRIOR_ROUND) { LOG.trace("Received RoundChange Payload for a prior round. targetRound={}", targetRound); return; } final Optional<Collection<RoundChange>> result = roundChangeManager.appendRoundChangeMessage(message); if (result.isPresent()) { LOG.debug( "Received sufficient RoundChange messages to change round to targetRound={}", targetRound); if (messageAge == FUTURE_ROUND) { startNewRound(targetRound.getRoundNumber()); } final RoundChangeArtifacts roundChangeArtifacts = RoundChangeArtifacts.create(result.get()); if (finalState.isLocalNodeProposerForRound(targetRound)) { currentRound.startRoundWith( roundChangeArtifacts, TimeUnit.MILLISECONDS.toSeconds(clock.millis())); } } } IbftBlockHeightManager(
      final BlockHeader parentHeader,
      final IbftFinalState finalState,
      final RoundChangeManager roundChangeManager,
      final IbftRoundFactory ibftRoundFactory,
      final Clock clock,
      final MessageValidatorFactory messageValidatorFactory); @Override void handleBlockTimerExpiry(final ConsensusRoundIdentifier roundIdentifier); @Override void roundExpired(final RoundExpiry expire); @Override void handleProposalPayload(final Proposal proposal); @Override void handlePreparePayload(final Prepare prepare); @Override void handleCommitPayload(final Commit commit); @Override void handleRoundChangePayload(final RoundChange message); @Override long getChainHeight(); @Override BlockHeader getParentBlockHeader();  }### Answer:
@Test public void onRoundChangeReceptionRoundChangeManagerIsInvokedAndNewRoundStarted() { final ConsensusRoundIdentifier futureRoundIdentifier = createFrom(roundIdentifier, 0, +2); final RoundChange roundChange = messageFactory.createRoundChange(futureRoundIdentifier, Optional.empty()); when(roundChangeManager.appendRoundChangeMessage(any())) .thenReturn(Optional.of(singletonList(roundChange))); when(finalState.isLocalNodeProposerForRound(any())).thenReturn(false); final IbftBlockHeightManager manager = new IbftBlockHeightManager( headerTestFixture.buildHeader(), finalState, roundChangeManager, roundFactory, clock, messageValidatorFactory); verify(roundFactory).createNewRound(any(), eq(0)); manager.handleRoundChangePayload(roundChange); verify(roundChangeManager, times(1)).appendRoundChangeMessage(roundChange); verify(roundFactory, times(1)) .createNewRound(any(), eq(futureRoundIdentifier.getRoundNumber())); }
@Test public void whenSufficientRoundChangesAreReceivedAProposalMessageIsTransmitted() { final ConsensusRoundIdentifier futureRoundIdentifier = createFrom(roundIdentifier, 0, +2); final RoundChange roundChange = messageFactory.createRoundChange(futureRoundIdentifier, Optional.empty()); final RoundChangeCertificate roundChangCert = new RoundChangeCertificate(singletonList(roundChange.getSignedPayload())); when(roundChangeManager.appendRoundChangeMessage(any())) .thenReturn(Optional.of(singletonList(roundChange))); when(finalState.isLocalNodeProposerForRound(any())).thenReturn(true); final IbftBlockHeightManager manager = new IbftBlockHeightManager( headerTestFixture.buildHeader(), finalState, roundChangeManager, roundFactory, clock, messageValidatorFactory); reset(messageTransmitter); manager.handleRoundChangePayload(roundChange); verify(messageTransmitter, times(1)) .multicastProposal(eq(futureRoundIdentifier), any(), eq(Optional.of(roundChangCert))); }