isaacs / node-lru-cache

A fast cache that automatically deletes the least recently used items
http://isaacs.github.io/node-lru-cache/
ISC License
5.35k stars 353 forks source link

Mocking lru-cache TTL with vitest not working #345

Closed eakl closed 3 months ago

eakl commented 3 months ago

Using vitest, I manage to mock Date.now

it('should advance time', () => {
         const date = Date.now()
         vi.setSystemTime(date)

         vi.advanceTimersByTime(10)
         expect(Date.now()).toEqual(date + 10) // true

         vi.advanceTimersByTime(9)
         expect(Date.now()).toEqual(date + 19) // true

         vi.advanceTimersByTime(10)
         expect(Date.now()).toEqual(date + 29) // true
      })

But it has no effect on lru-cache TTL. Vitest controlled timers doesn't seem to affect LRU timer.

it('should expire ttl', () => {
         const lru = new LRUCache({ max: 10, updateAgeOnGet: false })

         const date = Date.now()
         vi.setSystemTime(date)

         lru.set('key', 1234, { ttl: 10 })

         vi.advanceTimersByTime(9) // advance time by 9 ms
         console.log(lru.getRemainingTTL('key')) // remaining ttl is still 9.xx ms, no effect on cache-lru clock
         expect(lru.get('key')).toBe(1234)

         vi.advanceTimersByTime(2) // advance time by 2 more ms, total 11
         console.log(lru.getRemainingTTL(1)) // remaining ttl is still 9.xx ms
         expect(lru.get('key')).toBeUndefined() // AssertionError: expected 1234 to be undefined
      })
isaacs commented 3 months ago

That's because lru-cache uses performance.now(), not Date.now(). Maybe check out clock-mock, which I use to test lru-cache myself.

eakl commented 3 months ago

It works with mock-clock but not with vitest (even after adding support to performance and passing tests successfully on performance.now()). Thanks @isaacs