anchor.diff:      });
   
       group('update expire cache', () {
  -      test('expire a set value after it has been updated', () {
  +      test('expire a set value after it has been updated', () async {
           final cache = newUpdateExpireCache(immediateLoader);
  -        return cache
  -            .set(1, '2')
  -            .then((_) => offset = const Duration(seconds: 20))
  -            .then((_) => cache.getIfPresent(1))
  -            .then((value) => expect(value, '2', reason: 'value is set'))
  -            .then((_) => cache.set(1, '3'))
  -            .then((_) => offset = const Duration(seconds: 40))
  -            .then((_) => cache.getIfPresent(1))
  -            .then((value) => expect(value, '3', reason: 'value is updated'))
  -            .then((_) => offset = const Duration(seconds: 41))
  -            .then((_) => cache.getIfPresent(1))
  -            .then(
  -                (value) => expect(value, isNull, reason: 'value has expired'));
  -      });
  -      test('loaded value expires', () {
  +        await expectLater(cache.set(1, '2'), completion('2'));
  +        offset = const Duration(seconds: 20);
  +        await expectLater(cache.getIfPresent(1), completion('2'));
  +        await expectLater(cache.set(1, '3'), completion('3'));
  +        offset = const Duration(seconds: 40);
  +        await expectLater(cache.getIfPresent(1), completion('3'));
  +        offset = const Duration(seconds: 41);
  +        await expectLater(cache.getIfPresent(1), completion(isNull));
  +      });
  +      test('loaded value expires', () async {
           final cache = newUpdateExpireCache(immediateLoader);
  -        return cache
  -            .get(1)
  -            .then((value) => expect(value, '1', reason: 'value is loaded'))
  -            .then((_) => offset = const Duration(seconds: 20))
  -            .then((_) => cache.getIfPresent(1))
  -            .then(
  -                (value) => expect(value, '1', reason: 'value is still present'))
  -            .then((_) => offset = const Duration(seconds: 21))
  -            .then((_) => cache.getIfPresent(1))
  -            .then((value) => expect(value, isNull, reason: 'value has expired'))
  -            .then((_) => cache.size())
  -            .then((size) => expect(size, 0, reason: 'cache should be empty'));
  -      });
  -      test('re-loaded value expires', () {
  +        await expectLater(cache.get(1), completion('1'));
  +        offset = const Duration(seconds: 20);
  +        await expectLater(cache.getIfPresent(1), completion('1'));
  +        offset = const Duration(seconds: 21);
  +        await expectLater(cache.getIfPresent(1), completion(isNull));
  +        await expectLater(cache.size(), completion(0));
  +      });
  +      test('re-loaded value expires', () async {
           var counter = 0;
           final cache = newUpdateExpireCache((key) {
             counter++;
             return immediateLoader(key);
           });
  -        return cache
  -            .get(0)
  -            .then((value) => expect(value, '0', reason: 'value is loaded'))
  -            .then((value) => expect(counter, 1, reason: 'loaded once'))
  -            .then((_) => offset = const Duration(seconds: 20))
  -            .then((_) => cache.get(0))
  -            .then(
  -                (value) => expect(value, '0', reason: 'value is still present'))
  -            .then((value) => expect(counter, 1, reason: 'still loaded once'))
  -            .then((_) => offset = const Duration(seconds: 21))
  -            .then((_) => cache.get(0))
  -            .then((value) => expect(value, '0', reason: 'value is reloaded'))
  -            .then((value) => expect(counter, 2, reason: 'value loaded again'));
  -      });
  -      test('reap expired items', () {
  +        await expectLater(cache.get(0), completion('0'));
  +        expect(counter, 1);
  +        offset = const Duration(seconds: 20);
  +        await expectLater(cache.get(0), completion('0'));
  +        expect(counter, 1);
  +        offset = const Duration(seconds: 21);
  +        await expectLater(cache.get(0), completion('0'));
  +        expect(counter, 2);
  +      });
  +      test('reap expired items', () async {
           final cache = newUpdateExpireCache(immediateLoader);
  -        return cache
  -            .set(1, '1')
  -            .then((_) => offset = const Duration(seconds: 21))
  -            .then((_) => cache.size())
  -            .then(
  -                (size) => expect(size, 1, reason: 'cache has not been reaped'))
  -            .then((_) => cache.reap())
  -            .then((size) => expect(size, 1, reason: 'one item should be gone'))
  -            .then((_) => cache.size())
  -            .then((size) => expect(size, 0, reason: 'cache should be empty'));
  +        await cache.set(1, 'foo');
  +        offset = const Duration(seconds: 21);
  +        await expectLater(cache.size(), completion(1));
  +        await expectLater(cache.reap(), completion(1));
  +        await expectLater(cache.size(), completion(0));
         });
       });
       group('access expire cache', () {
  -      test('expire a set value after it has been updated', () {
  +      test('expire a set value after it has been updated', () async {
           final cache = newAccessExpireCache(immediateLoader);
  -        return cache
  -            .set(1, '2')
  -            .then((_) => offset = const Duration(seconds: 20))
  -            .then((_) => cache.getIfPresent(1))
  -            .then((value) => expect(value, '2', reason: 'value is set'))
  -            .then((_) => cache.set(1, '3'))
  -            .then((_) => offset = const Duration(seconds: 40))
  -            .then((_) => cache.getIfPresent(1))
  -            .then((value) => expect(value, '3', reason: 'value is updated'))
  -            .then((_) => offset = const Duration(seconds: 61))
  -            .then((_) => cache.getIfPresent(1))
  -            .then(
  -                (value) => expect(value, isNull, reason: 'value has expired'));
  -      });
  -      test('loaded value expires', () {
  +        await cache.set(1, 'foo');
  +        offset = const Duration(seconds: 20);
  +        await expectLater(cache.getIfPresent(1), completion('foo'));
  +        await cache.set(1, 'bar');
  +        offset = const Duration(seconds: 40);
  +        await expectLater(cache.getIfPresent(1), completion('bar'));
  +        offset = const Duration(seconds: 61);
  +        await expectLater(cache.getIfPresent(1), completion(isNull));
  +      });
  +      test('loaded value expires', () async {
           final cache = newAccessExpireCache(immediateLoader);
  -        return cache
  -            .get(1)
  -            .then((value) => expect(value, '1', reason: 'value is loaded'))
  -            .then((_) => offset = const Duration(seconds: 20))
  -            .then((_) => cache.getIfPresent(1))
  -            .then(
  -                (value) => expect(value, '1', reason: 'value is still present'))
  -            .then((_) => offset = const Duration(seconds: 41))
  -            .then((_) => cache.getIfPresent(1))
  -            .then((value) => expect(value, isNull, reason: 'value has expired'))
  -            .then((_) => cache.size())
  -            .then((size) => expect(size, 0, reason: 'cache should be empty'));
  -      });
  -      test('re-loaded value expires', () {
  +        await expectLater(cache.get(1), completion('1'));
  +        offset = const Duration(seconds: 20);
  +        await expectLater(cache.getIfPresent(1), completion('1'));
  +        offset = const Duration(seconds: 41);
  +        await expectLater(cache.getIfPresent(1), completion(isNull));
  +        await expectLater(cache.size(), completion(0));
  +      });
  +      test('re-loaded value expires', () async {
           var counter = 0;
           final cache = newAccessExpireCache((key) {
             counter++;
             return immediateLoader(key);
           });
  -        return cache
  -            .get(0)
  -            .then((value) => expect(value, '0', reason: 'value is loaded'))
  -            .then((value) => expect(counter, 1, reason: 'loaded once'))
  -            .then((_) => offset = const Duration(seconds: 20))
  -            .then((_) => cache.get(0))
  -            .then(
  -                (value) => expect(value, '0', reason: 'value is still present'))
  -            .then((value) => expect(counter, 1, reason: 'still loaded once'))
  -            .then((_) => offset = const Duration(seconds: 41))
  -            .then((_) => cache.get(0))
  -            .then((value) => expect(value, '0', reason: 'value is reloaded'))
  -            .then((value) => expect(counter, 2, reason: 'value loaded again'));
  -      });
  -      test('reap expired items', () {
  +        await expectLater(cache.get(0), completion('0'));
  +        expect(counter, 1);
  +        offset = const Duration(seconds: 20);
  +        await expectLater(cache.get(0), completion('0'));
  +        expect(counter, 1);
  +        offset = const Duration(seconds: 41);
  +        await expectLater(cache.get(0), completion('0'));
  +        expect(counter, 2);
  +      });
  +      test('reap expired items', () async {
           final cache = newAccessExpireCache(immediateLoader);
  -        return cache
  -            .set(1, '1')
  -            .then((_) => offset = const Duration(seconds: 120))
  -            .then((_) => cache.size())
  -            .then(
  -                (size) => expect(size, 1, reason: 'cache has not been reaped'))
  -            .then((_) => cache.reap())
  -            .then((size) => expect(size, 1, reason: 'one item should be gone'))
  -            .then((_) => cache.size())
  -            .then((size) => expect(size, 0, reason: 'cache should be empty'));
  +        await cache.set(1, '1');
  +        offset = const Duration(seconds: 120);
  +        await expectLater(cache.size(), completion(1));
  +        await expectLater(cache.reap(), completion(1));
  +        await expectLater(cache.size(), completion(0));
         });
       });
     });
  
positive.code:         Cache.lru(loader: loader, maximumSize: 5);
  
      group('constructors', () {
        test('missing lru', () {
          expect(() => Cache.lru(), throwsArgumentError);
        });
        test('non positive max size', () {
          expect(() => Cache.lru(loader: immediateLoader, maximumSize: 0),
              throwsArgumentError);
  
negative.code:         Cache.fifo(loader: loader, maximumSize: 5);
  
      group('constructors', () {
        test('non positive max size', () {
          expect(() => Cache.fifo(loader: immediateLoader, maximumSize: 0),
              throwsArgumentError);
  