如何jest.mock "git-simple" branchLocal函数?

How to jest.mock "git-simple" branchLocal function?

我使用 simple-git 包。我有以下功能:

import simpleGit from 'simple-git';

/**
 * The function returns the ticket Id, is presents, in the branch name
 * @returns ticket Id
 */
export const getTicketIdFromBranchName = async (ticketRegex: RegExp) => {
    const git = simpleGit();

    try {
        const localBranches = await git.branchLocal();
        const currentBranch = localBranches.current;
        const currentBranchTicketMatches = currentBranch.match(ticketRegex);

        if (currentBranchTicketMatches) {
            return currentBranchTicketMatches[0];
        }

        return null;
    } catch {
        return null;
    }
};

我尝试为此功能创建单元测试:

import { getTicketIdFromBranchName } from '@/utils/git-info';

const TICKET_ID_REGEX = /((?<!([A-Z]{1,10})-?)[A-Z]+-\d+)/.source;

describe('[utils/git-info]', () => {
    it('getTicketIdFromBranchName | Function should proper ticket Id when there is one', async () => {
        const ticketId = 'CLO-1234';

        jest.mock('simple-git', () => {
            const mGit = {
                branchLocal: jest.fn(() => Promise.resolve({ current: `${ticketId} DUMMY TEST` })),
            };

            return jest.fn(() => mGit);
        });

        const result = await getTicketIdFromBranchName(new RegExp(TICKET_ID_REGEX));

        expect(result === ticketId).toEqual(true);
    });
});

但是单元测试失败了。我说我希望得到 true 但它在最后一行得到了 false

我想我用错了jest.mock

官方documentationjest.mock的使用有重点说明。

Note: In order to mock properly, Jest needs jest.mock('moduleName') to be in the same scope as the require/import statement.

您在测试用例函数范围内调用 jest.mock('moduleName'),但在模块范围内调用 import git-info 模块。这就是 mock 不起作用的原因。

在测试用例函数中使用require('moduleName')await import('moduleName')require/importjest.mock() 语句的顺序 重要。

git-info.js:

import simpleGit from 'simple-git';

/**
 * The function returns the ticket Id, is presents, in the branch name
 * @returns ticket Id
 */
export const getTicketIdFromBranchName = async (ticketRegex) => {
  const git = simpleGit();

  try {
    const localBranches = await git.branchLocal();
    const currentBranch = localBranches.current;
    const currentBranchTicketMatches = currentBranch.match(ticketRegex);

    if (currentBranchTicketMatches) {
      return currentBranchTicketMatches[0];
    }

    return null;
  } catch {
    return null;
  }
};

git-info.test.js:

const TICKET_ID_REGEX = /((?<!([A-Z]{1,10})-?)[A-Z]+-\d+)/.source;

describe('[utils/git-info]', () => {
  it('getTicketIdFromBranchName | Function should proper ticket Id when there is one', async () => {
    const { getTicketIdFromBranchName } = await import('./git-info');
    const ticketId = 'CLO-1234';

    jest.mock(
      'simple-git',
      () => {
        const mGit = {
          branchLocal: jest.fn(() => Promise.resolve({ current: `${ticketId} DUMMY TEST` })),
        };

        return jest.fn(() => mGit);
      },
      { virtual: true }
    );

    const result = await getTicketIdFromBranchName(new RegExp(TICKET_ID_REGEX));

    expect(result === ticketId).toEqual(true);
  });
});

测试结果:

 PASS  Whosebug/71808909/git-info.test.js (7.439 s)
  [utils/git-info]
    ✓ getTicketIdFromBranchName | Function should proper ticket Id when there is one (6892 ms)

-------------|---------|----------|---------|---------|-------------------
File         | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------|---------|----------|---------|---------|-------------------
All files    |   84.62 |       50 |     100 |   81.82 |                   
 git-info.js |   84.62 |       50 |     100 |   81.82 | 19-21             
-------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        8.215 s, estimated 9 s

包版本:"jest": "^26.6.3"