模拟的npm模块以开玩笑的方式返回空对象

时间:2019-12-27 13:34:36

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

我在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;

我的代码中有一个套接字包装,其中包含一些便捷方法,其中包括以下片段:

// 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":{}}

正如我在以字符串形式记录模块时在日志中看到的那样,该模拟返回空对象,而不是模拟的实现。我到处都看过,但似乎找不到解决方案。

1 个答案:

答案 0 :(得分:0)

来自此文档: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;语句。