如何使用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'
},
}
7条答案
按热度按时间l5tcr1uw1#
我使用了:
很容易在测试之外添加和恢复功能。
lyfkaqu12#
下面是我在测试文件顶部的内容:
在从该文件运行的测试中,
Math.random
始终返回0.5
。这一想法应该得到充分的赞扬:https://stackoverflow.com/a/40460395/2140998,它阐明了这个覆盖是测试特定的。我的
Object.create
只是我额外的一点警告,避免篡改Math
本身的内部。llmtgqce3#
我采用了斯图尔特·瓦特的解决方案(有点忘乎所以)。Stuart的解决方案很好,但我对随机数生成器总是输出0.5的想法不感兴趣--似乎有些情况下你需要依赖一些方差。我还想模拟
crypto.randomBytes
作为我的密码salts(使用Jest服务器端)。我花了一些时间在这上面,所以我想我应该分享一下知识。我注意到的一件事是,即使你有一个可重复的数字流,引入一个对
Math.random()
的新调用可能会搞砸所有后续调用。我发现了一个解决这个问题的方法。这个方法应该适用于几乎任何你需要模拟的随机事物。(side注意:如果你想窃取这个,你需要安装Chance.js-
yarn/npm add/install chance
)要模拟
Math.random
,请将以下代码放入package.json
的{"jest":{"setupFiles"}
数组所指向的文件中:你会注意到
Math.random()
现在有了一个参数--seed,这个seed可以是一个字符串,这意味着当你写代码的时候,你可以通过名字来调用你想要的随机数生成器,当我在代码中添加了一个测试来检查它是否工作的时候,我没有把种子放进去。它搞砸了我以前嘲笑的Math.random()
快照。但是当我把它改为Math.random('mathTest')
时,它创建了一个名为“mathTest”的新生成器,并停止从默认生成器截取序列。我还模拟了
crypto.randomBytes
作为我的密码salts,所以当我编写生成salts的代码时,我可能会写crypto.randomBytes(32, 'user sign up salt').toString('base64')
,这样我就可以很确定没有对crypto.randomBytes
的后续调用会扰乱我的序列。如果有人想用这种方式模仿
crypto
,请将以下代码放入<rootDir>/__mocks__/crypto.js
:然后调用
jest.mock('crypto')
(同样,我在我的一个“setupFiles”中有它),因为我发布了它,所以我继续使它与回调方法兼容(尽管我不打算那样使用它)。这两段代码传递了these tests的所有17个键(我为
beforeEach()
创建了__clearChances__
函数-它只是删除了chances
散列中的所有键)更新:我已经用了几天了,我认为它工作得很好,唯一的问题是我认为也许更好的策略是创建一个
Math.useSeed
函数,在需要Math.random
的测试的顶部运行db2dz4w84#
我会问自己以下几个问题:
c
的值是否足够?有时候有一种方法可以将随机值的生成封装在 Mock 中,然后在测试中覆盖生成,只返回已知值。这是我代码中的一种常见做法。如何模拟new Date()这样的构造函数听起来与 jestjs 中的方法类似。
xe55xuns5#
您始终可以使用jest-mock-random
但它提供了比第一个答案中提出的嘲笑它多一点的功能。
例如,您可以在
testmockRandomWith(0.6);
之前使用,并且您在test中的Math.random将始终返回此可预测值fjaof16o6#
模拟字面上的随机数据并不是正确的测试方法,正如上面所说,这个问题有点宽泛,因为“如何测试输出是随机的函数”需要你对输出进行统计分析,以确保有效的随机性--这很可能是伪随机数生成器的创建者所做的。
相反,推断“输出是随机的”意味着您希望确保函数正常运行,而不管随机数据如何,然后只是模拟Math.random调用以返回满足特定条件的数字(覆盖任何变化)就足够了。该函数是第三方边界,虽然需要测试,并不是基于我的推断所测试的,除非它是--在这种情况下,请参考上面的段落。
b09cbbtk7#
我同意理查德巴克的回答。奇怪的是,在写他的回答时有0票,而赞成票和接受的完全错过了重点。我猜这个线程太老了。
**如何使用Jest测试一个随机输出的函数?**这不是一个Jest问题,甚至不是一个编程问题,而是一个统计学(甚至哲学)问题。据我所知,数学只能最终证明一个序列是非随机的,这意味着它有一个可识别的模式。Math.random()和所有其他伪随机数生成器一样,最终都会产生一个模式,因为它们是算法。
最好的可行建议是畏缩的回答。测试返回范围并键入。所有其他建议都消除了应该测试的输出随机性,使“随机性测试”毫无意义。