Nodejs 如何在单元测试中 mock path.basename 的运行环境

Nodejs 如何在单元测试中 mock path.basename 的运行环境

nodejs basename 方法会依据运行环境的不同选择不同的实现。

    it('can get basename correctly', () => {
        expect(path.win32.basename('C:\\foo\\bar\\baz.txt')).toBe('baz.txt')
        expect(path.posix.basename('C:\\foo\\bar\\baz.txt')).toBe('C:\\foo\\bar\\baz.txt')
    })

上面的测试用例无论在那个平台执行都是正确的。

    it('can get basename correctly on windows', () => {
        expect(path.basename('C:\\foo\\bar\\baz.txt')).toBe('baz.txt')
    })

上面的测试用例只有在 Windows 系统执行时,才是通过的。问题来了,如何在 mac 上 mock nodejs 的运行环境,指定其为 Windows ,让这个测试用例通过?

朋友们有没有想法,一直没找到解决思路,困扰好久了。


7 回复

我觉得换个方向可能会更好,即: windows 单测只在 windows 系统中运行。
你可以封装一个 it.win() 或者 onlyWin(),亦或者在 it 单测上下文中通过 process.platform 来跳过 expect 语句的执行。

这样一来,你的单测也具备一定的维护性

Nestjs仿小米商城企业级Nodejs RBAC 微服务项目实战视频教程+Docker Swarm K8s云原生分布式部署系统学习:https://www.itying.com/goods-1139.html


谢谢回复,检测 platform 变量让特定的测试用例只在特定的平台上运行,这也是一个思路。我感觉这个思路最大问题是我要有 windows 系统才能运行我 windows 相关的单测,现在我手头并没有 windows 设备。

我有这样的需求是因为业务逻辑涉及到不同文件系统的兼容性,手头上只有 mac ,对 windows 相关逻辑不太放心,想在单元测试中覆盖下。假如能找到合适的 mock 方法,每次运行完测试后,把环境变量还原,单测维护性也还好。

可以试着在 docker 、CI\CD pipeline 、Github Actions 中来运行测试用例,这样不同的系统都能够测试到

github actions 配置多个操作系统

docker 和 github actions 确实可行,谢谢大家

最终,在单元测试里 mock 的方向,我也找到了一个解决方案,使用 proxyquire mock path 库:
js<br>const path = require('path');<br>const proxyquire = require('proxyquire');<br><br>const rule = proxyquire('../../../lib/rules/no-index', {<br> path: { ...path.win32, '@global': true },<br>});<br>

![https://stackoverflow.com/questions/72934150/how-do-i-mock-node-js-running-time-operating-system-in-a-unit-test-for-path-mo]( https://stackoverflow.com/questions/72934150/how-do-i-mock-node-js-running-time-operating-system-in-a-unit-test-for-path-mo)

在 Node.js 中进行单元测试时,mock 内置模块(如 path.basename)的方法通常涉及使用 Jest 或 Sinon 等测试库。以下是使用 Jest 来 mock path.basename 的示例。

首先,确保你已经安装了 Jest:

npm install --save-dev jest

接下来,在你的测试文件中,你可以使用 Jest 的 jest.spyOnmockImplementation 方法来 mock path.basename

// 假设你的被测试文件是 myModule.js
const path = require('path');
const myModule = require('./myModule');

describe('myModule tests', () => {
  beforeEach(() => {
    // Mock path.basename
    jest.spyOn(path, 'basename').mockImplementation((filePath, ext) => {
      // 自定义返回值
      return 'mockedBasename';
    });
  });

  afterEach(() => {
    // 清除 mock
    path.basename.mockRestore();
  });

  test('should use mocked path.basename', () => {
    const result = myModule.someFunction('/some/path/file.txt');
    expect(result).toBe('mockedBasename'); // 根据你的实际逻辑调整
  });
});

在上述代码中,jest.spyOn(path, 'basename') 用于创建一个 spy 并 mock path.basename 方法。mockImplementation 方法允许你定义自定义的返回值。beforeEachafterEach 钩子确保在每个测试之前和之后设置和清除 mock。

通过这种方式,你可以在单元测试中有效地 mock path.basename 的运行环境。

回到顶部