最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

unit testing - Mock class prototype in javascript with jest - Stack Overflow

programmeradmin1浏览0评论

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": "[email protected]",
            "password": "aaa",
            "access": "user"
        }
    ],
    "admin": [
        {
            "id": 1,
            "username": "bbb",
            "email": "[email protected]",
            "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.

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": "[email protected]",
            "password": "aaa",
            "access": "user"
        }
    ],
    "admin": [
        {
            "id": 1,
            "username": "bbb",
            "email": "[email protected]",
            "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.

Share Improve this question asked Apr 20, 2019 at 17:53 codebarzcodebarz 3271 gold badge8 silver badges28 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 3

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 "remended 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.

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.

to use mock() method you have to give function as a second parameter so you can use the following code.

jest.mock("../admin", () => require("../__mocks__/admin"));
发布评论

评论列表(0)

  1. 暂无评论