@Test
public void testAsyncIcon() {

  CompletableFuture<Icon> futureIcon = new CompletableFuture();
  Icon placeholder = EmptyIcon.create(50, 40);
  AtomicInteger loaded = new AtomicInteger(0);
  AsyncIcon asyncIcon = new AsyncIcon(futureIcon, placeholder, loaded::incrementAndGet);
  assertEquals(0, loaded.get());
  assertEquals(50, asyncIcon.getIconWidth());
  assertEquals(40, asyncIcon.getIconHeight());
  AtomicInteger painted = new AtomicInteger(0);
  Icon mockIcon = new Icon() {
    @Override
    public void paintIcon(Component c, Graphics g, int x, int y) {
      painted.incrementAndGet();
    }
    @Override
    public int getIconWidth() {
      return 50;
    }
    @Override
    public int getIconHeight() {
      return 40;
    }
  };
  // This will still paint the placeholder since the Future is still pending
  asyncIcon.paintIcon(null, null, 1, 2);
  assertEquals(0, painted.get());
  futureIcon.complete(mockIcon);
  assertEquals(1, loaded.get());
  asyncIcon.paintIcon(null, null, 1, 2);
  assertEquals(1, painted.get());
  // Now check with an icon that it's already loaded (we didn't have to wait for it)
  asyncIcon = new AsyncIcon(
    CompletableFuture.completedFuture(mockIcon),
    placeholder,
    loaded::incrementAndGet);
  assertEquals(2, loaded.get());
  asyncIcon.paintIcon(null, null, 1, 2);
  assertEquals(2, painted.get());
}