2017-01-10 8 views
5

Как проверить функцию, которая выводится случайным образом с помощью Jest? Как это:Как проверить функцию, которая выводится случайным образом с помощью Jest?

import cuid from 'cuid'; 
const functionToTest = (value) => ({ 
    [cuid()]: { 
     a: Math.random(), 
     b: new Date().toString(), 
     c: value, 
    } 
}); 

Так выход functionToTest('Some predictable value') будет что-то вроде:

{ 
    'cixrchnp60000vhidc9qvd10p': { 
    a: 0.08715126430943698, 
    b: 'Tue Jan 10 2017 15:20:58 GMT+0200 (EET)', 
    c: 'Some predictable value' 
    }, 
} 
+1

Как вы думаете, «тест ... этот выход случайный» означает даже? Переверните монету, и вы можете получить головы дважды подряд; если это невозможно, это не случайно. Пункт «случайный» - это * вы не знаете, какое значение вы ищете *. На практике вы можете запустить функцию дважды для одного входа и ожидать разные выходы, но некоторые (очень низкие) проценты времени, которые он должен выполнить, даже с рабочим кодом. –

+0

Конечно, тестовая случайность - это глупость. Я спрашиваю, как ** проверить ** такие случаи в принципе. Я просто не знаю, как это сделать. –

+0

Ключ здесь, а не случайность. Может быть, случайная часть должна быть ограничена или так. Я тестирую noob, поэтому задаюсь вопросом. –

ответ

12

Вот что я положил в верхней части моего тестового файла:

const mockMath = Object.create(global.Math); 
mockMath.random =() => 0.5; 
global.Math = mockMath; 

В тестах бежать из этого файла, Math.random всегда возвращает 0.5.

Полный кредит должен пойти на это по идее: https://stackoverflow.com/a/40460395/2140998, в котором уточняется, что эта перезапись является специфичной для теста. Мой Object.create - это всего лишь моя дополнительная дополнительная осторожность, не допуская вмешательства со встроенными средствами Math.

+0

сладкий! Хотелось бы, чтобы это было в документах. – looshi

3

я задаю себе следующие вопросы:

  • ли мне действительно нужно, чтобы проверить случайный выход ? Если мне нужно, я бы скорее всего проверил диапазоны или удостоверился, что получил номер в допустимом формате, а не само значение
  • Достаточно ли проверить значение для c?

Иногда есть способ инкапсуляции генерации случайной величины в Mock и переопределить поколение в тесте, чтобы вернуть только известные значения. Это обычная практика в моем коде. How to mock a constructor like new Date() похоже на аналогичный подход в jestjs.

+0

Отлично, вот что я хотел знать. Это не просто прямой ответ, а нечто, что стоит за целью тестирования. Благодаря! –

1

Я принял решение Стюарта Уотта и побежал с ним (и немного увлекся). Решение Стюарта хорошее, но мне было неловко думать, что генератор случайных чисел всегда выплевывает 0,5 - кажется, что бывают ситуации, когда вы рассчитываете на некоторую дисперсию. Я также хотел высмеять crypto.randomBytes для моих паролей солей (используя сервер Jest). Я потратил немного времени на это, поэтому решил, что поделюсь знаниями.

Одна из вещей, которые я заметил, это то, что даже если у вас есть повторяемый поток чисел, введение нового вызова в Math.random() может испортить все последующие вызовы. Я нашел способ обойти эту проблему. Этот подход должен применяться практически ко всем случайным вещам, которые вам нужно высмеять.

(примечание стороны: если вы хотите, чтобы украсть это, вам нужно установить Chance.js - yarn/npm add/install chance)

издеваться Math.random, поставить это в один из файлов, указанных в вашем package.json «ы {"jest":{"setupFiles"} массива:

const Chance = require('chance') 

const chances = {} 

const mockMath = Object.create(Math) 
mockMath.random = (seed = 42) => { 
    chances[seed] = chances[seed] || new Chance(seed) 
    const chance = chances[seed] 
    return chance.random() 
} 

global.Math = mockMath 

Вы заметите, что Math.random() теперь имеет параметр - семя. Это семя может быть строкой. Это означает, что, когда вы пишете свой код, вы можете вызвать генератор случайных чисел, который вы хотите по имени. Когда я добавил тест на код, чтобы проверить, сработало ли это, я не использовал его. Это привнесло мои ранее издевавшиеся снимки Math.random(). Но затем, когда я изменил его на Math.random('mathTest'), он создал новый генератор под названием «mathTest» и остановил перехват последовательности из стандартной.

Я также высмеивал crypto.randomBytes для моего пароля соли. Поэтому, когда я пишу код для создания моих солей, я могу написать crypto.randomBytes(32, 'user sign up salt').toString('base64'). Таким образом, я могу быть уверен, что никакой последующий вызов crypto.randomBytes не испортит мою последовательность.

Если кто-либо еще интересуется насмешкой crypto таким образом, вот как. Поместите этот код в <rootDir>/__mocks__/crypto.js:

const crypto = require.requireActual('crypto') 
const Chance = require('chance') 

const chances = {} 

const mockCrypto = Object.create(crypto) 
mockCrypto.randomBytes = (size, seed = 42, callback) => { 
    if (typeof seed === 'function') { 
    callback = seed 
    seed = 42 
    } 

    chances[seed] = chances[seed] || new Chance(seed) 
    const chance = chances[seed] 

    const randomByteArray = chance.n(chance.natural, size, { max: 255 }) 
    const buffer = Buffer.from(randomByteArray) 

    if (typeof callback === 'function') { 
    callback(null, buffer) 
    } 
    return buffer 
} 

module.exports = mockCrypto 

А потом просто позвонить jest.mock('crypto') (опять же, я его в одном из моих «SetupFiles»). Поскольку я выпускаю его, я пошел вперед и сделал его совместимым с методом обратного вызова (хотя я не собираюсь использовать его таким образом).

Этих два фрагмент кода пройти все 17 из these tests (я создал __clearChances__ функций для beforeEach() с - это просто удаляет все ключи от chances хэша)

Update: Использую это в течение нескольких дней, и теперь Я думаю, это работает очень хорошо. Единственное, я думаю, что, возможно, лучшей стратегией будет создание Math.useSeed функции, запущенного в верхней части тестов, которые требуют Math.random

0

Вы всегда можете использовать jest-mock-random

Но он предлагает немного больше функциональных возможностей, чем насмешливый это, как было предложено в первом ответе

 Смежные вопросы

  • Нет связанных вопросов^_^