### Question:
TransactionStateMachine implements StatementProcessor { @Override public StatementMetadata run( String statement, MapValue params ) throws KernelException { return run( statement, params, null, null, null ); } TransactionStateMachine( TransactionStateMachineSPI spi, AuthenticationResult authenticationResult, Clock clock ); State state(); @Override void beginTransaction( Bookmark bookmark ); @Override void beginTransaction( Bookmark bookmark, Duration txTimeout, Map<String,Object> txMetadata ); @Override StatementMetadata run( String statement, MapValue params ); @Override StatementMetadata run( String statement, MapValue params, Bookmark bookmark, Duration txTimeout, Map<String,Object> txMetaData ); @Override Bookmark streamResult( ThrowingConsumer<BoltResult, Exception> resultConsumer ); @Override Bookmark commitTransaction(); @Override void rollbackTransaction(); @Override boolean hasOpenStatement(); @Override void reset(); @Override void markCurrentTransactionForTermination(); @Override void validateTransaction(); @Override boolean hasTransaction();  }### Answer:
@Test void shouldUnbindTxAfterRun() throws Exception { KernelTransaction transaction = newTimedOutTransaction(); TransactionStateMachineV1SPI stateMachineSPI = newTransactionStateMachineSPI( transaction ); TransactionStateMachine stateMachine = newTransactionStateMachine( stateMachineSPI ); stateMachine.run( "SOME STATEMENT", null ); verify( stateMachineSPI, times( 1 ) ).unbindTransactionFromCurrentThread(); }
@Test void shouldThrowDuringRunIfPendingTerminationNoticeExists() throws Exception { KernelTransaction transaction = newTimedOutTransaction(); TransactionStateMachineV1SPI stateMachineSPI = newTransactionStateMachineSPI( transaction ); TransactionStateMachine stateMachine = newTransactionStateMachine( stateMachineSPI ); stateMachine.ctx.pendingTerminationNotice = Status.Transaction.TransactionTimedOut; TransactionTerminatedException e = assertThrows( TransactionTerminatedException.class, () -> stateMachine.run( "SOME STATEMENT", null ) ); assertEquals( Status.Transaction.TransactionTimedOut, e.status() ); }
@Test void shouldCloseResultAndTransactionHandlesWhenExecutionFails() throws Exception { KernelTransaction transaction = newTransaction(); BoltResultHandle resultHandle = newResultHandle( new RuntimeException( "some error" ) ); TransactionStateMachineV1SPI stateMachineSPI = newTransactionStateMachineSPI( transaction, resultHandle ); TransactionStateMachine stateMachine = newTransactionStateMachine( stateMachineSPI ); RuntimeException e = assertThrows( RuntimeException.class, () -> stateMachine.run( "SOME STATEMENT", null ) ); assertEquals( "some error", e.getMessage() ); assertNull( stateMachine.ctx.currentResultHandle ); assertNull( stateMachine.ctx.currentResult ); assertNull( stateMachine.ctx.currentTransaction ); }