admin管理员组

文章数量:1225101

I have a function which I try to test using Vitest.

This is my function (I test the exported one):

import os from 'node:os';

import { AI_COMMIT_IGNORED_FILES } from '../constants/ai-commit';
import { asyncExec } from './os';

/**
 * The function returns array of files paths that are in staged mode
 * @returns array of files paths in staged mode
 */
const getStagedFiles = async () => {
    const gitCommand = 'git diff --name-only --cached --relative .';
    const { stdout: filesOutput, stderr } = await asyncExec(gitCommand);

    if (stderr) {
        throw new Error(stderr);
    }

    const filesList = filesOutput.split(os.EOL).filter(Boolean);

    return filesList;
};


/**
 * The function returns the "git diff" command output for relevant staged files in the commit
 * @returns "git diff" output as a string
 */
export const getStagedFilesDiff = async () => {
    const stagedFiles = await getStagedFiles();
    const filteredFiles = stagedFiles.filter((file) => !AI_COMMIT_IGNORED_FILES.includes(file));

    const gitCommand = `git diff --staged -- ${filteredFiles.join(' ')}`;
    const { stdout: diffOutput, stderr } = await asyncExec(gitCommand);

    if (stderr) {
        throw new Error(stderr);
    }

    return diffOutput;
};

And this is the asyncExec function:

import { exec } from 'node:child_process';
import util from 'node:util';

export const asyncExec = util.promisify(exec);

I wrote the following test:

import { describe, it, expect, vi } from 'vitest';

import { asyncExec } from '@/utils/os';
import { getStagedFilesDiff } from '@/utils/git-info';

vi.mock('@/utils/os');

describe('[utils/git-info]', () => {
    describe('getStagedFilesDiff()', () => {
        it('should throw an error when "asyncExec" throws', () => {
            vi.mocked(asyncExec).mockRejectedValueOnce(undefined);

            expect(() => getStagedFilesDiff()).toThrowError();
        });
    });
});

But then I got the error:


Vitest caught 1 unhandled error during the test run.
This might cause false positive tests. Resolve unhandled errors to make sure your tests are not affected.


This error originated in "tests/utils/git-info.spec.ts" test file. It doesn't mean the error was thrown inside the file itself, but while it was running.
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
 ELIFECYCLE  Test failed. See above for more details.

I have followed this: /api/expect.html#tothrowerror

So I don't understand why doesn't it work..?


I have also tried:

        it('should throw an error when "asyncExec" throws', async () => {
            vi.mocked(asyncExec).mockRejectedValueOnce(undefined);

            await expect(() => getStagedFilesDiff()).rejects.toThrowError(undefined);
        });

the error is:

AssertionError: expected [Function] to throw an error

Then I wrapped the getStagedFilesDiff function with try {} catch {} as follows:

export const getStagedFilesDiff = async () => {
    try {
        const stagedFiles = await getStagedFiles();
        const filteredFiles = stagedFiles.filter((file) => !AI_COMMIT_IGNORED_FILES.includes(file));

        if (filteredFiles.length === 0) {
            return null;
        }

        const gitCommand = `git diff --staged -- ${filteredFiles.join(' ')}`;
        const { stdout: diffOutput, stderr } = await asyncExec(gitCommand);

        if (stderr) {
            throw new Error(`Failed to get "git diff" output of staged files with error:\n${stderr}`);
        }

        return diffOutput;
    } catch {
        throw new Error();
    }
};

Then the test completed successfully.

I have a function which I try to test using Vitest.

This is my function (I test the exported one):

import os from 'node:os';

import { AI_COMMIT_IGNORED_FILES } from '../constants/ai-commit';
import { asyncExec } from './os';

/**
 * The function returns array of files paths that are in staged mode
 * @returns array of files paths in staged mode
 */
const getStagedFiles = async () => {
    const gitCommand = 'git diff --name-only --cached --relative .';
    const { stdout: filesOutput, stderr } = await asyncExec(gitCommand);

    if (stderr) {
        throw new Error(stderr);
    }

    const filesList = filesOutput.split(os.EOL).filter(Boolean);

    return filesList;
};


/**
 * The function returns the "git diff" command output for relevant staged files in the commit
 * @returns "git diff" output as a string
 */
export const getStagedFilesDiff = async () => {
    const stagedFiles = await getStagedFiles();
    const filteredFiles = stagedFiles.filter((file) => !AI_COMMIT_IGNORED_FILES.includes(file));

    const gitCommand = `git diff --staged -- ${filteredFiles.join(' ')}`;
    const { stdout: diffOutput, stderr } = await asyncExec(gitCommand);

    if (stderr) {
        throw new Error(stderr);
    }

    return diffOutput;
};

And this is the asyncExec function:

import { exec } from 'node:child_process';
import util from 'node:util';

export const asyncExec = util.promisify(exec);

I wrote the following test:

import { describe, it, expect, vi } from 'vitest';

import { asyncExec } from '@/utils/os';
import { getStagedFilesDiff } from '@/utils/git-info';

vi.mock('@/utils/os');

describe('[utils/git-info]', () => {
    describe('getStagedFilesDiff()', () => {
        it('should throw an error when "asyncExec" throws', () => {
            vi.mocked(asyncExec).mockRejectedValueOnce(undefined);

            expect(() => getStagedFilesDiff()).toThrowError();
        });
    });
});

But then I got the error:


Vitest caught 1 unhandled error during the test run.
This might cause false positive tests. Resolve unhandled errors to make sure your tests are not affected.


This error originated in "tests/utils/git-info.spec.ts" test file. It doesn't mean the error was thrown inside the file itself, but while it was running.
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
 ELIFECYCLE  Test failed. See above for more details.

I have followed this: https://vitest.dev/api/expect.html#tothrowerror

So I don't understand why doesn't it work..?


I have also tried:

        it('should throw an error when "asyncExec" throws', async () => {
            vi.mocked(asyncExec).mockRejectedValueOnce(undefined);

            await expect(() => getStagedFilesDiff()).rejects.toThrowError(undefined);
        });

the error is:

AssertionError: expected [Function] to throw an error

Then I wrapped the getStagedFilesDiff function with try {} catch {} as follows:

export const getStagedFilesDiff = async () => {
    try {
        const stagedFiles = await getStagedFiles();
        const filteredFiles = stagedFiles.filter((file) => !AI_COMMIT_IGNORED_FILES.includes(file));

        if (filteredFiles.length === 0) {
            return null;
        }

        const gitCommand = `git diff --staged -- ${filteredFiles.join(' ')}`;
        const { stdout: diffOutput, stderr } = await asyncExec(gitCommand);

        if (stderr) {
            throw new Error(`Failed to get "git diff" output of staged files with error:\n${stderr}`);
        }

        return diffOutput;
    } catch {
        throw new Error();
    }
};

Then the test completed successfully.

Share Improve this question edited Apr 22, 2023 at 18:32 Tal Rofe asked Apr 21, 2023 at 9:05 Tal RofeTal Rofe 1,8443 gold badges25 silver badges64 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 15

I managed to resolve this issue by doing:

        it('should throw an error when "asyncExec" throws', async () => {
            vi.mocked(asyncExec).mockRejectedValueOnce(new Error());

            await expect(() => getStagedFilesDiff()).rejects.toThrowError();
        });

本文标签: