### Question:
JobRuntimeExtensionPoint extends BaseRuntimeExtensionPoint implements JobListener { @Override public void jobFinished( final Job job ) throws KettleException { if ( job == null ) { return; } log.warn( Messages.getString( "INFO.JobAnalyzeStarting", job.getJobname() ) ); logMinimal( Messages.getString( "INFO.JobAnalyzeStarting", job.getJobname() ) ); if ( shouldCreateGraph( job ) ) { runAnalyzers( job ); } if ( allowedAsync() ) { createLineGraphAsync( job ); } else { createLineGraph( job ); } }  @Override void callExtensionPoint( LogChannelInterface logChannelInterface, Object o ); @Override void jobFinished( final Job job ); @Override void jobStarted( Job job ); static String getFilename( Job job ); static String getFilename( JobMeta jobMeta );  }### Answer:
@Test public void testJobFinished() throws Exception { JobRuntimeExtensionPoint ext = spy( jobExtensionPoint ); ext.jobFinished( null ); verify( ext, never() ).populateExecutionProfile( Mockito.any( IExecutionProfile.class ), eq( job ) ); ext.jobFinished( job ); verify( ext, times( 1 ) ).populateExecutionProfile( Mockito.any( IExecutionProfile.class ), eq( job ) ); verify( ext, times( 1 ) ).runAnalyzers( eq( job ) ); verify( ext, times( 2 ) ).shouldCreateGraph( eq( job ) ); verify( lineageWriter, times( 1 ) ).outputLineageGraph( Matchers.any( LineageHolder.class ) ); Job mockJob = spy( job ); Result result = mock( Result.class ); when( mockJob.getResult() ).thenReturn( result ); ext.jobFinished( mockJob ); verify( ext, times( 1 ) ).populateExecutionProfile( Mockito.any( IExecutionProfile.class ), eq( mockJob ) ); }