首页 > 解决方案 > 用玩笑在javascript中模拟类原型

问题描述

我目前正在进行一个项目,我需要mock一定constructor class prototype要运行测试,所以它不直接处理我的database. 我已经尝试过研究并发现我需要将importmodule放入我的mock文件中,然后export将其放入我的文件中testjest.setMock()用于替换我test.js文件中的模块。以下是我尝试过的代码。

我有Admin constructor class一个删除功能,prototype负责从db

管理员.js

function Admin(username, email, password, access) {
    Users.call(this, username, email, password, access);
}

Admin.constructor = Admin;

Admin.prototype.deleteSingleUser = function(id, accountType) {
   this.id = id;
   this.accountType = accountType;

    let response = "";

    if(this.accountType === "admin") {
        for(let i in dbData.admin) {
            if(dbData.admin[i].id === this.id) {
                dbData.admin.splice(i, 1);
                fs.writeFileSync('db.json', JSON.stringify(dbData, null, 2));
                console.log(dbData.admin);
                response = "Account successfully deleted";
            }
            else {
                response = "There is no user registered with this ID";
            }
        }
    }
    else if(this.accountType === "user") {
        for(let i in dbData.users) {
            if(dbData.users[i].id === this.id) {
                dbData.users.splice(i, 1);
                fs.writeFileSync('db.json', JSON.stringify(dbData, null, 2));
                console.log(dbData.users);
                response = "Account successfully deleted";
            }
            else {
                response = "There is no user registered with this ID";
            }
        }
    }
    else {
        response = "Kindly use a valid account type";
    }
    console.log(response);
    return response;
};

然后在我的__mocks__目录中,我有一个admin.js包含mock数据库和mock删除代码的文件

__mocks__/admin.js

//Imported the admin.js

let Admin = require("../admin");

//Created a mock database
let mockDb = {
    "users": [
        {
            "id": 1,
            "username": "aaa",
            "email": "aaa@gmail.com",
            "password": "aaa",
            "access": "user"
        }
    ],
    "admin": [
        {
            "id": 1,
            "username": "bbb",
            "email": "bbb@gmail.com",
            "password": "bbb",
            "access": "admin"
        }
    ]
} 

//My mock delete function

Admin.prototype.deleteSingleUser = function(id, accountType) {
    this.id = id;
    this.accountType = accountType;

    let response = "";

    if (this.accountType === "admin") {
        if(mockDb.admin[0].id === this.id) {
            response = "Account successfully deleted";
        }
        else {
            response = "There is no user registered with this ID";
        }
    }
    else if (this.accountType === "user") {
        if(mockDb.users[0].id === this.id) {
            response = "Account successfully deleted";
        }
        else {
            response = "There is no user registered with this ID";
        }
    }
    console.log("Its using the mock");
    return response;
};
module.exports = Admin;

然后在我__test__的文件夹中,我有一个test.js包含我的测试用例的文件

__test__/test.js

const Admin = require("../admin");
jest.setMock("Admin", require("../__mocks__/admin"));

test("Should check if admin can delete with a wrong id", () => {
    let response = Admin.prototype.deleteSingleUser(0, "user");
    expect(response).toBe("There is no user registered with this ID");
});
test("Should check if admin can delete a user", () => {
    let response = Admin.prototype.deleteSingleUser(1, "user");
    expect(response).toBe("Account successfully deleted");
});

两个测试用例都没有通过,但都是throw一个error说法

测试套件无法运行

无法从“test.js”中找到模块“Admin”

2 | const Users = require("../main");

3 | const Admin = require("../admin");

4 | jest.setMock("Admin", require("../ mocks /admin"));

| ^

5 | const order = require("../order");

6 | 让 mocks = require("../ mocks /admin");

7 | 让 dbData = JSON.parse(fs.readFileSync('db.json'));

在 Resolver.resolveModule (node_modules/jest-resolve/build/index.js:229:17)

在 Object.setMock (测试/test.js:4:6)

我觉得我做的不对,但我似乎无法指出。请问是什么问题,我该如何解决?谢谢。

标签: javascriptunit-testingjestjs

解决方案


你根本不需要使用jest.setMock

您只需要通过执行以下操作来激活您为用户模块创建的手动模拟:

jest.mock('../admin');  // <= activate the manual mock

细节

文档jest.setMock声明它只应在“极少数情况下”使用,即“即使是手动模拟也不适合您的目的”,并补充说“建议使用它jest.mock()

在这种情况下,您不需要做任何事情,jest.setMock因此最佳做法是使用jest.mock.


推荐阅读