【问题标题】:Mocked npm module returns empty objects in jest模拟的 npm 模块开玩笑地返回空对象
【发布时间】:2019-12-27 13:34:36
【问题描述】:

我在 TypeScript 环境中关注 this guide。我的目标是在我的测试中模拟 socket.io-client 实现,以便我可以在即时消息传递组件中模拟套接字事件。

// __mocks__/socket.io-client.js

// SOURCE: https://medium.com/free-code-camp/testing-socket-io-client-app-using-jest-and-react-testing-library-9cae93c070a3

let EVENTS = {};
function emit(event, ...args) {
  EVENTS[event].forEach(func => func(...args));
}
const socket = {
  on(event, func) {
    if (EVENTS[event]) {
      return EVENTS[event].push(func);
    }
    EVENTS[event] = [func];
  },
  emit,
};

export const io = {
  connect() {
    return socket;
  },
};

// Additional helpers, not included in the real socket.io-client,just for out test.
// to emulate server emit.
export const serverSocket = { emit };

// cleanup helper
export function cleanup() {
  EVENTS = {};
}
export default io;

我的代码中有一个带有一些便捷方法的套接字包装器,其中包括这个 sn-p:

// SocketWrapper.ts
import * as io from 'socket.io-client';

/* Code removed for brevity */

    console.log(io);
    console.log(JSON.stringify(io));

    this.socket = io.connect(

当我运行测试时,我收到以下错误:

 FAIL  src/components/User/components/Messages/Messages.test.tsx
  ● Test suite failed to run

    TypeError: io.connect is not a function

      55 |     console.log(JSON.stringify(io));
      56 | 
    > 57 |     this.socket = io.connect(


      at MessagesService.connect (src/lib/classes/SocketWrapper.ts:69:19)
      at MessagesService.connect (src/services/Messages.service.ts:29:11)
      at new MessagesService (src/services/Messages.service.ts:25:10)
      at Object.<anonymous> (src/components/User/components/Messages/Messages.tsx:9:17)
      at Object.<anonymous> (src/components/User/User.tsx:3:1)
      at Object.<anonymous> (src/testUtils/pages/UserPage.tsx:10:1)
      at Object.<anonymous> (src/components/User/components/Messages/Messages.test.tsx:2:1)

  console.log src/lib/classes/SocketWrapper.ts:54
    { cleanup: [Function: cleanup],
      io: { connect: [Function: connect] },
      serverSocket: { emit: [Function: emit] },
      default: { connect: [Function: connect] } }

  console.log src/lib/classes/SocketWrapper.ts:55
    {"io":{},"serverSocket":{},"default":{}}

当我将模块记录为字符串时,您可以在日志中看到,模拟返回空对象而不是我的模拟实现。我到处寻找,但似乎找不到解决方案。

【问题讨论】:

  • 尝试使用import io from 'socket.io-client' 而不是import * as io from 'socket.io-client'
  • @slideshowp2 就是这样!愿意解释为什么会发生这种情况吗?另外,请随时将此添加为您的答案,我会接受。

标签: node.js reactjs typescript unit-testing jestjs


【解决方案1】:

来自此文档:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import

name 参数是“模块对象”的名称,它将用作一种命名空间来引用导出。导出参数指定单个命名导出,而 import * as name 语法导入所有这些。

这意味着如果你使用import * as io from 'socket.io-client'io 是一种命名空间。

在您的模拟文件中,io 是一个对象,export default io;

如果您使用import * as io from 'socket.io-client'io 变量的值将是:

{ // <- the outer object is io namespace
  io: { // <- this is the io object you defined in your mock file
    connect() {
      return socket;
    }
  }
}

使用import io from 'socket.io-client',它将从中导入默认对象:

const io = {
  connect() {
    return socket;
  },
};

如果你坚持使用import * as io from 'socket.io-client' 声明。 改变

export const io = {
  connect() {
    return socket;
  },
};

收件人:

export function connect() {
  return socket;
}

并删除export default io; 声明。

【讨论】:

    猜你喜欢
    • 2020-03-05
    • 1970-01-01
    • 1970-01-01
    • 2020-08-20
    • 2021-07-03
    • 2018-10-23
    • 1970-01-01
    • 2018-07-25
    • 2017-07-01
    相关资源
    最近更新 更多