### Question:
CountedMethodBean { @Counted(name = "countedMethod", absolute = true) public T countedMethod(Callable<T> callable) { try { return callable.call(); } catch (Exception cause) { throw new RuntimeException(cause); } }  @Counted(name = "countedMethod", absolute = true) T countedMethod(Callable<T> callable);  }### Answer:
@Test @InSequence(4) public void removeCounterFromRegistry() { assertThat("Counter is not registered correctly", registry.getCounters(), hasKey(COUNTER_NAME)); Counter counter = registry.getCounters().get(COUNTER_NAME); registry.remove(COUNTER_NAME); try { bean.countedMethod(new Callable<Long>() { @Override public Long call() throws Exception { return null; } }); } catch (Exception cause) { assertThat(cause, is(instanceOf(IllegalStateException.class))); assertThat(cause.getMessage(), is(equalTo("No counter with name [" + COUNTER_NAME + "] found in registry [" + registry + "]"))); assertThat("Counter count is incorrect", counter.getCount(), is(equalTo(COUNTER_COUNT.get()))); return; } fail("No exception has been re-thrown!"); }
@Test @InSequence(3) public void callCountedMethodOnce() throws InterruptedException, TimeoutException { assertThat("Counter is not registered correctly", registry.getCounters(), hasKey(COUNTER_NAME)); Counter counter = registry.getCounters().get(COUNTER_NAME); final Exchanger<Long> exchanger = new Exchanger<>(); Thread thread = new Thread(new Runnable() { @Override public void run() { try { exchanger.exchange(bean.countedMethod(new Callable<Long>() { @Override public Long call() throws Exception { exchanger.exchange(0L); return exchanger.exchange(0L); } })); } catch (InterruptedException cause) { throw new RuntimeException(cause); } } }); final AtomicInteger uncaught = new AtomicInteger(); thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { @Override public void uncaughtException(Thread t, Throwable e) { uncaught.incrementAndGet(); } }); thread.start(); exchanger.exchange(0L, 5L, TimeUnit.SECONDS); assertThat("Counter count is incorrect", counter.getCount(), is(equalTo(COUNTER_COUNT.incrementAndGet()))); Long random = 1 + Math.round(Math.random() * (Long.MAX_VALUE - 1)); exchanger.exchange(random, 5L, TimeUnit.SECONDS); assertThat("Counted method return value is incorrect", exchanger.exchange(0L), is(equalTo(random))); assertThat("Counter count is incorrect", counter.getCount(), is(equalTo(COUNTER_COUNT.decrementAndGet()))); thread.join(); assertThat("Exception thrown in method call thread", uncaught.get(), is(equalTo(0))); }