@Test
public void retryReachesMaximumAndForwardException() throws Throwable {

  RuntimeException oops = new RuntimeException("oops");
  when(joinPoint.proceed()).thenThrow(oops);
  when(compensable.forwardRetries()).thenReturn(3);
  try {
    aspect.advise(joinPoint, compensable);
    expectFailing(RuntimeException.class);
  } catch (RuntimeException e) {
    assertThat(e.getMessage(), is("oops"));
  }
  assertThat(messages.size(), is(4));
  // TxStartedEvent retry 1
  TxEvent startedEvent1 = messages.get(0);
  assertThat(startedEvent1.globalTxId(), is(globalTxId));
  assertThat(startedEvent1.localTxId(), is(newLocalTxId));
  assertThat(startedEvent1.parentTxId(), is(localTxId));
  assertThat(startedEvent1.type(), is(EventType.TxStartedEvent));
  assertThat(startedEvent1.forwardRetries(), is(3));
  assertThat(startedEvent1.retryMethod(),
      is(this.getClass().getDeclaredMethod("doNothing").toString()));
  // TxStartedEvent retry 2
  TxEvent startedEvent2 = messages.get(1);
  assertThat(startedEvent2.localTxId(), is(newLocalTxId));
  assertThat(startedEvent2.type(), is(EventType.TxStartedEvent));
  assertThat(startedEvent2.forwardRetries(), is(2));
  // TxStartedEvent retry 3
  TxEvent startedEvent3 = messages.get(2);
  assertThat(startedEvent3.localTxId(), is(newLocalTxId));
  assertThat(startedEvent3.type(), is(EventType.TxStartedEvent));
  assertThat(startedEvent3.forwardRetries(), is(1));
  // TxAbortedEvent
  assertThat(messages.get(3).type(), is(EventType.TxAbortedEvent));
  assertThat(omegaContext.globalTxId(), is(globalTxId));
  assertThat(omegaContext.localTxId(), is(localTxId));
}