简体   繁体   中英

Mock class prototype in javascript with jest

I am currently on a project and i need to mock a certain constructor class prototype to run test so it doesn't deal directly with my database . I already tried researching and discovered i need to import the module into my mock file and then export it to my test file and use jest.setMock() to replace the module in my test.js file. Below is the code to what i have tried.

I have an Admin constructor class with a delete function in its prototype responsible for deleting from db

admin.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;
};

Then in my __mocks__ directory i have an admin.js file containing a mock database and my mock delete code

__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;

Then in my __test__ folder i have a test.js file with my test cases

__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");
});

Neither of the test cases pass but both throw an error saying

Test suite failed to run

Cannot find module 'Admin' from 'test.js'

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

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

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

| ^

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

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

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

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

at Object.setMock ( test /test.js:4:6)

I feel i am not doing something right but i can't seem to point it out. Please what is the issue and how do i fix it? Thanks.

Your code seems alright. You just need to set your jest.setMock() to point to the right file.

jest.setMock() takes two parameters jest.setMock(moduleName, moduleExports) . The moduleName should point to the file containing the module your are mocking and moduleExports to the file containing your mock module. In other words, change in your

__test__/test.js

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

to

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

And you should be fine.

You don't need to use jest.setMock at all.

You just need to activate the manual mock you created for your user module by doing this:

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

Details

The docs for jest.setMock state that it should only be used on "extremely rare occasions" when "even a manual mock isn't suitable for your purposes" and adds that it is " recommended to use jest.mock() instead. "

In this case you aren't doing anything that would require jest.setMock so best practice is to activate your manual mock with jest.mock .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM