Шутка фальшивые таймеры с обещаниями - PullRequest
0 голосов
/ 01 июля 2018

У меня возникли небольшие проблемы с тем, чтобы среда тестирования Jest (версия 23.2.0) работала хорошо при использовании комбинации фальшивых таймеров и обещаний. Куда я иду не так?

Допустим, у меня есть следующий модуль:

// timing.js

export const timeout = ms =>
  new Promise(resolve => {
    setTimeout(resolve, ms)
  })

И мой тестовый файл выглядит так:

// timing.test.js

import { timeout } from './timing'

describe('timeout()', () => {
  beforeEach(() => {
    jest.useFakeTimers()
  })

  it('resolves in a given amount of time', () => {
    const spy = jest.fn()

    timeout(100).then(spy)
    expect(spy).not.toHaveBeenCalled()

    jest.advanceTimersByTime(100)
    expect(spy).toHaveBeenCalled()
  })
})

Сбой при следующем выводе:

● timeout › resolves in a given amount of time

expect(jest.fn()).toHaveBeenCalled()

Expected mock function to have been called, but it was not called.

  15 |
  16 |     jest.advanceTimersByTime(100)
> 17 |     expect(spy).toHaveBeenCalled()
     |                 ^
  18 |   })
  19 | })
  20 |

  at Object.<anonymous> (src/timing.test.js:17:17)

Однако, если я уберу обещание:

// timing.js
export const timeout = ms => ({
  then: resolve => {
    setTimeout(resolve, ms)
  }
})

... тест пройдёт

timeout
  ✓ resolves in a given amount of time (5ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.304s

UPDATE

Хотя это не самое элегантное решение, я сейчас использую тест ниже. Это работает, но я все еще заинтригован, почему оригинальный не

import { timeout } from './timing'

describe('timeout', () => {
  it('resolves in a given amount of time', done => {
    setTimeout(() => done(new Error('it didn\'t resolve or took longer than expected')), 10)
    return timeout(9).then(done)
  })
})

1 Ответ

0 голосов
/ 02 июля 2018

На данный момент не поддерживается

Вы не делаете ничего плохого - в данный момент это не работает - извините. Чтобы это сработало с нашей стороны, должно произойти следующее:

  • Jest необходимо объединить текущую работу, чтобы объединить lolex в качестве реализации фальшивого таймера здесь https://github.com/facebook/jest/pull/5171
  • Lolex необходимо поддерживать выполнение обещаний - мы обсуждали это с командой V8 на недавнем саммите коллабораторов Node.js. Это разоблачит ловушку, которую мы будем использовать, чтобы сделать что-то вроде advanceTimeByTime(100) и работать с обещаниями.

Проблема в том, что суть .then(spy) вызывается только позже .

Поскольку мы являемся добровольцами, у нас нет конкретных сроков. Я надеюсь, что SimenB осуществит слияние в ближайшие 2-3 месяца, и я продолжу работу с командой V8 в следующем месяце.

Что вы можете сделать сейчас

Вы всегда можете написать асинхронный тест:

// note this is an async function now
it('resolves in a given amount of time', async () => {
  // this is in a promise.reoslve.then to not 'lock' on the await
  Promise.resolve().then(() => jest.advanceTimersByTime(100));
  await timeout(100);
});

Вы можете добавить ожидания после тайм-аута, если есть что-то еще, чего вы хотите ждать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...