跳转到主要内容
版本:26.倍

Ручніімітації

手动模拟用于使用模拟数据消除功能。例如,您可能希望创建一个允许使用假数据的手动模拟,而不是访问网站或数据库等远程资源。这将确保您的测试将是快速的,而不是不稳定的。

模拟用户模块#

手动模拟是通过在__mocks__ /紧挨着模块的子目录。例如,要模拟一个被调用的模块用户在里面模型目录,创建一个名为user.js.把它放在了模型/ __模仿__目录中。请注意,__mocks__文件夹是区分大小写的,因此命名目录__MOCKS__会破坏一些系统。

当我们在测试中要求该模块时,明确地呼叫jest.mock (' / moduleName’)。要求

模拟节点模块#

如果您嘲笑的模块是节点模块(例如:lodash)时,应将mock放置在__mocks__邻近的目录node_modules(除非你配置指向项目根目录以外的文件夹),将是自动嘲笑。没有必要明确地打电话jest.mock(“module_name”)

范围模块可以通过在与范围名称的名称匹配的目录结构中创建文件来嘲笑。例如,要模拟一个调用的范围模块@scope /项目名称,创建文件__mocks__/@scope/project-name.js.,形成了@范围/相应的目录。

警告:如果我们想模拟Node的核心模块(例如:fs或者路径),然后显式地调用jest.mock(路径)要求,因为默认情况下核心节点模块是不被模拟的。

Приклади#

├──配置
├──__mocks__
│└──fs.js.
├──模型
│├──__mocks__
││├─ramstein(2)——cat sound效果器整理www.catsound.js
│└──user.js.
├──node_modules
└──观点

当给定模块存在手动模拟时,Jest的模块系统将在显式调用时使用该模块jest.mock('modulename')。但是,当automock被设置为真的,将使用手动模拟实现,而不是自动创建的模拟,即使jest.mock('modulename')不被称为。要选择退出此行为,您需要明确地调用jest.unmock(“moduleName”)在应使用实际模块实现的测试中。

注意:为了恰当地嘲弄,Jest需要jest.mock('modulename')与之相同的范围要求/导入陈述。

下面是一个精心设计的示例,其中我们有一个模块,提供给定目录中所有文件的摘要。在本例中,我们使用内核(内置)fs模块。

// filesummarizer.js.
使用严格的 ;
常量 fs = 需要 ( 'fs' ) ;
功能 summarizefilesindirectorysync. ( 目录 ) {
返回 fs readdirSync ( 目录 ) 地图 ( 文件名 => ( {
目录 ,
文件名 ,
} ) ) ;
}
出口 summarizefilesindirectorysync. = summarizefilesindirectorysync. ;

由于我们希望尝试避免实际击中磁盘(这非常缓慢而脆弱),我们为此创建了手动模拟fs模块通过扩展自动模拟。我们的手动模拟将实现自定义版本fs用于测试的api:

// __mocks __ / fs.js
使用严格的 ;
常量 路径 = 需要 ( “路径” ) ;
常量 fs = 开玩笑 createMockFromModule ( 'fs' ) ;
//这是一个自定义函数,我们的测试可以在设置期间使用它来指定
//“模拟”文件系统上的文件应该是什么样子的
//使用' fs ' api。
mockFiles = 对象 创造 ( 无效的 ) ;
功能 __setmockfiles. ( newMockFiles ) {
mockFiles = 对象 创造 ( 无效的 ) ;
( 常量 文件 newMockFiles ) {
常量 dir = 路径 目录名 ( 文件 ) ;
如果 ( ! mockFiles ( dir ] ) {
mockFiles ( dir ] = ( ] ;
}
mockFiles ( dir ] ( 路径 Basename. ( 文件 ) ) ;
}
}
//从特殊模型中读取的“readdirsync`的自定义版本”
//通过__setmockfiles设置文件列表
功能 readdirSync ( 目录路径 ) {
返回 mockFiles ( 目录路径 ] || ( ] ;
}
fs __setmockfiles. = __setmockfiles. ;
fs readdirSync = readdirSync ;
模块 出口 = fs ;

现在我们编写我们的测试。注意,我们需要明确地告知我们想要模仿fs模块,因为它是一个核心节点模块:

// __tests __ / filesummarizer-test.js
使用严格的 ;
开玩笑 嘲笑 ( 'fs' ) ;
描述 ( “listFilesInDirectorySync” , ( ) => {
常量 MOCK_FILE_INFO = {
“/道路/ / file1.js” : ”控制台。日志(“file1内容”),“ ,
“/道路/ / file2.txt” : 'file2内容' ,
} ;
beforeEach ( ( ) => {
//在每个测试之前设置一些模拟文件信息
需要 ( 'fs' ) __setmockfiles. ( MOCK_FILE_INFO ) ;
} ) ;
测试 ( '包括摘要目录中的所有文件' , ( ) => {
常量 filesumarizer = 需要 ( “. . / FileSummarizer” ) ;
常量 fileSummary = filesumarizer summarizefilesindirectorysync. (
' /路径/ ' ,
) ;
预计 ( fileSummary 长度 ) 托比 ( 2 ) ;
} ) ;
} ) ;

这里显示的示例模拟使用jest.createmockfrommodule.生成自动模拟,并覆盖其默认行为。这是推荐的方法,但完全是可选的。如果您根本不想使用自动模拟,您可以从模拟文件导出自己的函数。完全手动模拟的一个缺点是它们是手动的——这意味着当它们模拟的模块发生变化时,您必须手动更新它们。正因为如此,最好在自动模拟能够满足您的需要时使用或扩展它。

为了确保手动模拟和它的实际实现保持同步,可能需要使用实际模块jest.requireActual (moduleName)在您的手动模拟中,并在导出它之前使用模拟函数修改它。

此示例的代码可用示例/手动模拟

Використання з ES імпортом модулів#

如果您正在使用ES模块导入那么你通常会倾向于把你的进口测试文件顶部的语句。但是,通常需要指示Jest在模块使用之前使用模拟。因此,Jest将自动提升jest.mock调用模块顶部(在任何导入之前)。要了解更多有关此功能,请参阅这种回购

没有在JSDOM中实现的模拟方法#

如果某些代码使用了JSDOM (Jest使用的DOM实现)还没有实现的方法,则很难对其进行测试。这是一个例子window.matchMedia ()。jest回报TypeError:窗口。matchMedia是not a function没有正确地执行测试。

在这种情况下,是嘲笑matchMedia在测试文件中应该解决这个问题:

对象 defineProperty ( 窗口 , 'matchmedia' , {
可写的 : 真的 ,
价值 : 开玩笑 fn ( ) 模仿 ( 查询 => ( {
匹配 : ,
媒体 : 查询 ,
onchange : 无效的 ,
addListener : 开玩笑 fn ( ) , / /弃用
removeListener : 开玩笑 fn ( ) , / /弃用
addEventListener : 开玩笑 fn ( ) ,
removeEventListener : 开玩笑 fn ( ) ,
dispatchEvent : 开玩笑 fn ( ) ,
} ) ) ,
} ) ;

这是如果window.matchMedia ()在测试中调用的函数(或方法)中使用。如果window.matchMedia ()在被测试的文件中直接执行时,Jest报告同样的错误。在这种情况下,解决方案是将手动模拟移动到一个单独的文件中,并在测试中包含这个文件测试文件:

进口 ”。/ matchMedia.mock ' ; //必须在测试文件之前导入
进口 { 迈运 } ”。/ file-to-test ' ;
描述 ( 'mymethod()' , ( ) => {
//在这里测试方法…
} ) ;