Модульное тестирование функции, которая вызывает функцию, возвращающую обещание

#javascript #reactjs #unit-testing #jestjs

#javascript #reactjs #модульное тестирование #jestjs

Вопрос:

У меня есть функция, которая вызывает функцию, которая возвращает обещание. Вот код для этого:

 export const func1 = ({
  contentRef,
  onShareFile,
  t,
  trackOnShareFile,
}) => e => {
  trackOnShareFile()
  try {
    func2(contentRef).then(url => {
      onShareFile({
        title: t('shareFileTitle'),
        type: 'application/pdf',
        url,
      })
    }).catch(e => {
      if (process.env.NODE_ENV === 'development') {
        console.error(e)
      }
    })
    e.preventDefault()
  } catch (e) {
    if (process.env.NODE_ENV === 'development') {
      console.error(e)
    }
  }
}
 

И func2 это вызывается func1 примерно так:

 const func2 = element => {
  return import('html2pdf.js').then(html2pdf => {
    return html2pdf.default().set({ margin: 12 }).from(element).toPdf().output('datauristring').then(pdfAsString => {
      return pdfAsString.split(',')[1]
    }).then(base64String => {
      return `data:application/pdf;base64,${base64String}`
    })
  })
}
 

Сейчас я пытаюсь написать несколько модульных тестов func1 , но получаю некоторые проблемы. Что я сделал до сих пор, так это:

 describe('#func1', () => {
  it('calls `trackOnShareFile`', () => {
      // given
      const props = {
        trackOnShareFile: jest.fn(),
        onShareFile: jest.fn(),
        shareFileTitle: 'foo',
        contentRef: { innerHTML: '<div>hello world</div>' },
      }
      const eventMock = {
        preventDefault: () => {},
      }
      // when
      func1(props)(eventMock)
      // then
      expect(props.trackOnShareFile).toBeCalledTimes(1)
    })
    it('calls `onShareFile` prop', () => {
      // given
      const props = {
        trackOnShareFile: jest.fn(),
        onShareFile: jest.fn(),
        shareFileTitle: 'foo',
        contentRef: { innerHTML: '<div>hello world</div>' },
      }
      const eventMock = {
        preventDefault: () => {},
      }
      // when
      func1(props)(eventMock)
      // then
      expect(props.onShareFile).toBeCalledTimes(1)
    })
  })
 

Теперь первый тест проходит, но для второго теста я получаю Expected mock function to have been called one time, but it was called zero times. . Я не уверен, как правильно это проверить. Любая помощь приветствуется.

Комментарии:

1. Если первый проходит, а второй завершается неудачно, это означает только func2 сбой. Если вы удалите if (process.env.NODE_ENV === 'development') { и зарегистрируете ошибку, вы увидите ошибку. Во время тестов ваш env, вероятно test , скорее, чем development .

Ответ №1:

Хорошо, у меня это работает.

Для начала нам нужно смоделировать data-url-generator (это то, откуда мы импортируем func2 ). html2pdf Библиотека не работает в среде тестирования, потому что она использует поддельный DOM, который не полностью реализует графику canvas.

 jest.mock('./data-url-generator', () => jest.fn())
 

Тогда сам тест может быть написан следующим образом:

 it('invokes the `onShareFile` prop', done => {
    // given
    const t = key => `[${key}]`
    const urlMock = 'data:application/pdf;base64,PGh0bWw PGJvZHk PGRpdj5oZWxsbyB3b3JsZDwvZGl2PjwvYm9keT48L2h0bWw '
    const shareFileTitle = 'bar'
    const contentRef = document.createElement('div')
    contentRef.textContent = 'hello world'
    const trackOnShareFile = () => { }
    const eventMock = {
      preventDefault: () => { },
    }
    func2.mockResolvedValue(urlMock)
    const onShareFileMock = ({ title, type, url }) => {
      // then
      expect(func2).toHaveBeenCalledTimes(1)
      expect(func2).toHaveBeenCalledWith(contentRef)
      expect(title).toBe('[shareFileTitle]')
      expect(type).toBe('application/pdf')
      expect(url).toBe(urlMock)
      done()
    }
    // when
    func1({
      contentRef,
      onShareFile: onShareFileMock,
      shareFileTitle,
      t,
      trackOnShareFile,
    })(eventMock)
  })