如何测试私有而不是导出的函数

Posted

技术标签:

【中文标题】如何测试私有而不是导出的函数【英文标题】:How to test a private, not exported, function 【发布时间】:2021-02-22 09:23:48 【问题描述】:

我的bin 文件夹中有一个www.js 文件。负责启动我的服务器应用程序。

const http = require('http');

const app = require('../app'); // This is my express application instance.

http.createServer(app).listen(process.env.SERVER_PORT || 3000);

如您所见,这里没有导出。节点将运行此文件(cmd:node bin/www),我的服务器将启动。但是它仍然有一些我需要测试的逻辑。

我的测试用例:

它应该使用我的 express 实例创建服务器 如果没有提供环境变量,它应该从 3000 端口监听 它应该从环境变量提供的端口(如果已给定)进行侦听。

我使用jest 进行测试。

由于此文件不导出任何内容,因此我无法将其导入开玩笑的测试文件中。我现在如何测试?

【问题讨论】:

没有办法做到这一点。这是 JS 的基础。一个明显的解决方案是修复模块以导出您需要的东西。 【参考方案1】:

单元测试解决方案:

www.js:

const http = require('http');
const app = require('./app');

http.createServer(app).listen(process.env.SERVER_PORT || 3000);

app.js:

const express = require('express');
const app = express();

module.exports = app;

www.test.js:

const http = require('http');
const app = require('./app');

describe('64768906', () => 
  afterEach(() => 
    jest.resetModules();
  );
  afterAll(() => 
    jest.restoreAllMocks();
  );
  it('should create server with my express instance and  listen from port 3000', () => 
    const server =  listen: jest.fn() ;
    const createServerSpy = jest.spyOn(http, 'createServer').mockReturnValue(server);
    require('./www');
    expect(createServerSpy).toBeCalledWith(app);
    expect(server.listen).toBeCalledWith(3000);
  );
  it("should listen from port that is provided from environment variable if it's given.", () => 
    const SERVER_PORT = process.env.SERVER_PORT;
    process.env.SERVER_PORT = 4000;
    const server =  listen: jest.fn() ;
    const createServerSpy = jest.spyOn(http, 'createServer').mockReturnValue(server);
    require('./www');
    expect(createServerSpy).toBeCalledWith(app);
    expect(server.listen).toBeCalledWith('4000');
    process.env.SERVER_PORT = SERVER_PORT;
  );
);

单元测试结果:

 PASS  src/***/64768906/www.test.js (14.082s)
  64768906
    ✓ should create server with my express instance and  listen from port 3000 (12ms)
    ✓ should listen from port that is provided from environment variable if it's given. (22ms)

----------|----------|----------|----------|----------|-------------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files |      100 |      100 |      100 |      100 |                   |
 app.js   |      100 |      100 |      100 |      100 |                   |
 www.js   |      100 |      100 |      100 |      100 |                   |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        15.662s, estimated 17s

【讨论】:

以上是关于如何测试私有而不是导出的函数的主要内容,如果未能解决你的问题,请参考以下文章

告诉 phpunit 调用 public 而不是 private

检查通过 rewire 可见的(私有/非导出)函数上的方法调用

如何对非导出函数进行单元测试?

为啥这里的 String 构造函数应该被保护而不是私有?

如何使用私有构造函数对类进行单元测试?

TS4060:导出函数的返回类型已经或正在使用私有名称“类”