Jest 中的“<mock parameters> 类型的参数不可分配给‘never’类型的参数”是什么?

问题描述 投票:0回答:1

我在网上拿了一堆例子和 ChatGPT 代码来进行测试。我最终在参数

mockResolvedValue
下出现了一些红色波浪线,并出现错误:

Argument of type '{ email: string; }' is not assignable to parameter of type 'never'.ts(2345)
Argument of type 'string' is not assignable to parameter of type 'never'.ts(2345)

对于这两行:

        (getUserByEmail as jest.Mock).mockResolvedValue({ email: '[email protected]' });
        (bcrypt.hash as jest.MockedFunction<typeof bcrypt.hash>).mockResolvedValue('hashedPassword');

我的测试代码:

import React from "react";
import test from "node:test";
import { beforeEach, describe, expect, it, jest } from "@jest/globals";
import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";

import { checkNumberOfUsers, createNewUser, updateProfile } from "../domain/userControl";
import { createUser, getNumberOfUsers, getUserByEmail } from "../data/local/userRepo";
import { newUserSchema } from "@/schema/custom";
import bcrypt from 'bcryptjs';


jest.mock("@/data/local/userRepo", () => ({
    getNumberOfUsers: jest.fn(),
    getUserByEmail: jest.fn(),
    createUser: jest.fn(),
}));
jest.mock('bcryptjs', () => ({
    hash: jest.fn(),
}));
// describe("checkNumberOfUsers", () => {
//     beforeEach(() => {})
// });  


jest.mock("@/data/local/userRepo", () => ({
    getNumberOfUsers: jest.fn(),
    getUserByEmail: jest.fn(),
    createUser: jest.fn(),
}));

jest.mock('bcryptjs', () => ({
    hash: jest.fn(),
    compare: jest.fn(),
}));

describe('createNewUser', () => {
    beforeEach(() => {
        jest.clearAllMocks();
    });

    it("should call getNumberOfUsers", async () => {
        await checkNumberOfUsers();
        expect(getNumberOfUsers).toHaveBeenCalled();
    });

    it('returns error when fields are invalid', async () => {
        const invalidValues = {
            email: 'invalid-email',
            password: 'short',
            confirmPassword: 'short',
        };

        const result = await createNewUser(invalidValues);

        expect(result).toEqual({ error: 'Invalid fields!' });
    });

    it('returns error when passwords do not match', async () => {
        const values = {
            email: '[email protected]',
            password: 'password123',
            confirmPassword: 'password124',
        };

        const result = await createNewUser(values);

        expect(result).toEqual({ error: 'Passwords do not match!' });
    });

    it('returns error when email is already in use', async () => {
        const values = {
            email: '[email protected]',
            password: 'password123',
            confirmPassword: 'password123',
        };

        (getUserByEmail as jest.Mock).mockResolvedValue({ email: '[email protected]' });

        const result = await createNewUser(values);

        expect(getUserByEmail).toHaveBeenCalledWith(values.email);
        expect(result).toEqual({ error: 'Email already in use!' });
    });

    it('creates a new user successfully', async () => {
        const values = {
            email: '[email protected]',
            password: 'password123',
            confirmPassword: 'password123',
        };

        (getUserByEmail as jest.MockedFunction<typeof getUserByEmail>).mockResolvedValue(null);
        (bcrypt.hash as jest.MockedFunction<typeof bcrypt.hash>).mockResolvedValue('hashedPassword');
        (createUser as jest.MockedFunction<typeof createUser>).mockResolvedValue({ id: '1', email: '[email protected]', password: 'hashedPassword' });

        const result = await createNewUser(values);

        expect(getUserByEmail).toHaveBeenCalledWith(values.email);
        expect(bcrypt.hash).toHaveBeenCalledWith(values.password, 10);
        expect(createUser).toHaveBeenCalledWith({
            email: values.email,
            password: 'hashedPassword',
        });
        expect(result).toEqual({ success: 'User created.' });
    });
});

我要测试的代码:

"use server";

import {createUser, getNumberOfUsers, getUserByEmail, updateUser} from "@/data/local/userRepo";
import {newUserSchema, updateProfileSchema} from "@/schema/custom";
import {z} from "zod";
import bcrypt from "bcryptjs";

/**
 * Updates the user profile with the provided values.
 *
 * @param values - The values to update the profile with.
 * @returns An object with an error property if there was an error during the update, otherwise undefined.
 */
export async function updateProfile(values: z.infer<typeof updateProfileSchema>) {
    const validation = updateProfileSchema.safeParse(values)

    if (!validation.success) {
        return {error: "Invalid input"}
    }

    const {email, originalPassword, password} = validation.data

    const existingUser = await getUserByEmail(email)

    if (!existingUser) {
        return {error: "User not found"}
    }

    const passwordMatch = await bcrypt.compare(originalPassword, existingUser.password)

    if (!passwordMatch) {
        return {error: "Incorrect password"}
    }

    const hashedPassword = await bcrypt.hash(password, 10)

    await updateUser(existingUser.id, {email, password: hashedPassword})
}

export async function checkNumberOfUsers() {
    return await getNumberOfUsers()
}

export const createNewUser = async (values: z.infer<typeof newUserSchema>) => {
    const validatedFields = newUserSchema.safeParse(values);
    if (!validatedFields.success) {
        return {error: "Invalid fields!"};
    }

    const {email, password, confirmPassword} = validatedFields.data;

    if (password !== confirmPassword) {
        return {error: "Passwords do not match!"};
    }

    const hashedPassword = await bcrypt.hash(password, 10);

    const existingUser = await getUserByEmail(email);

    if (existingUser) {
        return {error: "Email already in use!"};
    }

    await createUser({
        email: email,
        password: hashedPassword,
    });

    // Add any other business logic here (e.g., checking credentials)
    return {success: "User created."};
};

我还尝试将

getUserByEmail
bcrypt.hash
更改为:

        getUserByEmail.mockResolvedValue({ email: '[email protected]' });
        bcrypt.hash.mockResolvedValue('hashedPassword');

以下类型为“openURL”的参数不能使用 Jest 分配给类型为“never”的参数,但我得到:

Property 'mockResolvedValue' does not exist on type '(email: string) => Promise<{ id: string; email: string; password: string; } | null>'.ts(2339)

和:

Property 'mockResolvedValue' does not exist on type '{ (s: string, salt: string | number): Promise<string>; (s: string, salt: string | number, callback?: ((err: Error | null, hash: string) => void) | undefined, progressCallback?: ((percent: number) => void) | undefined): void; }'.ts(2339)
typescript jestjs
1个回答
0
投票

深入研究,我发现您可以将mockreturnvalueonce用于“非异步函数”。虽然我不知道为什么会修复它并且我的测试用例通过了,因为我不知道 bcrypt 是否是异步函数。

        (getUserByEmail as jest.Mock).mockReturnValueOnce({ email: '[email protected]' });

        (bcrypt.hash as jest.MockedFunction<typeof bcrypt.hash>).mockReturnValueOnce();

© www.soinside.com 2019 - 2024. All rights reserved.