如何模拟节点readline?

Posted

技术标签:

【中文标题】如何模拟节点readline?【英文标题】:How to mock node readline? 【发布时间】:2019-06-01 06:58:00 【问题描述】:

当用户在 CLI 提示符中输入 y 时,getUserInput 调用一个函数:

export const getUserInput = (fn: () => void) => 
  const  stdin, stdout  = process;
  const rl = readline.createInterface( input: stdin, output: stdout );
  rl.question("Can you confirm? Y/N", (answer: string) => 
    if (answer.toLowerCase() === "y") 
      fn();
    
    rl.close();
  );
;

我需要为 getUserInput 模拟 Node 的 readline 创建一个测试。

目前我尝试了以下但没有成功,得到:

TypeError: rl.close is not a function

我的模拟实现是否正确,如果不正确,我该如何解决?

jest.mock("readline");
describe.only("program", () => 
    it.only("should execute a cb when user prompt in cli y", () => 
        const mock = jest.fn();
        getUserInput(mock);
        expect(mock).toHaveBeenCalled();
     );
 );

__mocks__/readline.ts(与node_module相邻的目录)

module.exports =
  createInterface :jest.fn().mockReturnValue(
    question:jest.fn().mockImplementationOnce((_questionTest, cb)=> cb('y'))
  )

【问题讨论】:

没问题!请在这里给minimal reproducible example;你打电话给jest.mock('readline')?在被测代码中是如何导入的? 从我链接到的文档中:"注意:为了正确模拟,Jest 需要 jest.mock('moduleName') 与 require/import 语句在同一范围内。" 不要把它放在规范中。 ^ 这个。其实,你可以把它放在规范中,但是你需要重新导入使用模拟模块的模块。 显而易见的路线是不依赖全局readline,并接受readline作为参数(默认),让您轻松通过测试。 【参考方案1】:

我能够通过添加一个模拟 close 函数来解决这个问题。

module.exports = 
  createInterface: jest.fn().mockReturnValue(
    question: jest.fn().mockImplementationOnce((_questionTest, cb) => cb("y")),
    close: jest.fn().mockImplementationOnce(() => undefined)
  )
;

【讨论】:

以上是关于如何模拟节点readline?的主要内容,如果未能解决你的问题,请参考以下文章

如何在玩笑测试中模拟“readline.createInterface”

如何在nodejs中获得同步readline,或使用异步“模拟”它?

Node.js实现终端输入(readline模块)

JavaScript模拟ATM业务

如何完成 sys.stdin.readlines() 输入?

如何取消 ConsoleReader.readLine()