### Question:
SchedulerApiaryRunner implements ApplicationRunner { @PreDestroy public void destroy() { try { log.info("Shutting down runner"); running.set(false); if (!lock.tryLock(RUNNER_DESTROY_TIMEOUT_SECONDS, TimeUnit.SECONDS)) { throw new BeekeeperException("Runner taking too long to shut down"); } } catch (InterruptedException e) { throw new BeekeeperException("Runner taking too long to shut down", e); } finally { try { schedulerApiary.close(); } catch (IOException e) { throw new BeekeeperException("Problem closing resources", e); } } log.info("Runner is shutdown"); } @Autowired  SchedulerApiaryRunner(SchedulerApiary schedulerApiary); @Override void run(ApplicationArguments args); @PreDestroy void destroy();  }### Answer:
@Test public void typicalRun() throws Exception { runRunner(); await().atMost(Duration.FIVE_SECONDS) .untilAsserted(() -> verify(schedulerApiary, atLeast(1)).scheduleBeekeeperEvent()); destroy(); verify(schedulerApiary).close(); }
@Test public void typicalRunWithException() throws Exception { doThrow(new RuntimeException()) .doNothing() .when(schedulerApiary) .scheduleBeekeeperEvent(); runRunner(); await().atMost(Duration.FIVE_SECONDS) .untilAsserted(() -> verify(schedulerApiary, atLeast(2)).scheduleBeekeeperEvent()); destroy(); verify(schedulerApiary).close(); }
@Test public void typicalRunSchedulerTimesoutOnDestroy() throws Exception { doAnswer(answer -> { Thread.sleep(15000L); return null; }).when(schedulerApiary) .scheduleBeekeeperEvent(); try { runRunner(); await().atMost(Duration.FIVE_SECONDS) .untilAsserted(() -> verify(schedulerApiary, atLeast(1)).scheduleBeekeeperEvent()); destroy(); fail("Runner should have thrown exception"); } catch (Exception e) { assertThat(e).isInstanceOf(BeekeeperException.class); assertThat(e.getMessage()).isEqualTo("Runner taking too long to shut down"); verify(schedulerApiary).close(); } }