### Question:
BoltRequestMessageReader { public void read( Neo4jPack.Unpacker unpacker ) throws IOException { try { doRead( unpacker ); } catch ( BoltIOException e ) { if ( e.causesFailureMessage() ) { Neo4jError error = Neo4jError.from( e ); connection.enqueue( stateMachine -> stateMachine.handleExternalFailure( error, externalErrorResponseHandler ) ); } else { throw e; } } } protected  BoltRequestMessageReader( BoltConnection connection, BoltResponseHandler externalErrorResponseHandler,
            List<RequestMessageDecoder> decoders ); void read( Neo4jPack.Unpacker unpacker );  }### Answer:
@Test public void shouldPropagateFatalError() throws Exception { Unpacker unpacker = mock( Unpacker.class ); RuntimeException error = new RuntimeException(); when( unpacker.unpackStructHeader() ).thenThrow( error ); BoltRequestMessageReader reader = new TestBoltRequestMessageReader( connectionMock(), responseHandlerMock(), emptyList() ); RuntimeException e = assertThrows( RuntimeException.class, () -> reader.read( unpacker ) ); assertEquals( error, e ); }
@Test public void shouldHandleErrorThatCausesFailureMessage() throws Exception { Unpacker unpacker = mock( Unpacker.class ); BoltIOException error = new BoltIOException( Status.General.UnknownError, "Hello" ); when( unpacker.unpackStructHeader() ).thenThrow( error ); BoltStateMachine stateMachine = mock( BoltStateMachine.class ); BoltConnection connection = new SynchronousBoltConnection( stateMachine ); BoltResponseHandler externalErrorResponseHandler = responseHandlerMock(); BoltRequestMessageReader reader = new TestBoltRequestMessageReader( connection, externalErrorResponseHandler, emptyList() ); reader.read( unpacker ); verify( stateMachine ).handleExternalFailure( Neo4jError.from( error ), externalErrorResponseHandler ); }
@Test public void shouldThrowForUnknownMessage() throws Exception { Unpacker unpacker = mock( Unpacker.class ); when( unpacker.unpackStructSignature() ).thenReturn( 'a' ); RequestMessageDecoder decoder = new TestRequestMessageDecoder( 'b', responseHandlerMock(), mock( RequestMessage.class ) ); BoltRequestMessageReader reader = new TestBoltRequestMessageReader( connectionMock(), responseHandlerMock(), singletonList( decoder ) ); BoltIOException e = assertThrows( BoltIOException.class, () -> reader.read( unpacker ) ); assertEquals( Status.Request.InvalidFormat, e.status() ); assertFalse( e.causesFailureMessage() ); assertEquals( "Message 0x61 is not a valid message signature.", e.getMessage() ); }
@Test public void shouldDecodeKnownMessage() throws Exception { Unpacker unpacker = mock( Unpacker.class ); when( unpacker.unpackStructSignature() ).thenReturn( 'a' ); RequestMessage message = mock( RequestMessage.class ); BoltResponseHandler responseHandler = responseHandlerMock(); RequestMessageDecoder decoder = new TestRequestMessageDecoder( 'a', responseHandler, message ); BoltStateMachine stateMachine = mock( BoltStateMachine.class ); BoltConnection connection = new SynchronousBoltConnection( stateMachine ); BoltRequestMessageReader reader = new TestBoltRequestMessageReader( connection, responseHandlerMock(), singletonList( decoder ) ); reader.read( unpacker ); verify( stateMachine ).process( message, responseHandler ); }