React Jest:如何模拟服务?

发布于 2025-02-11 03:01:29 字数 2939 浏览 1 评论 0原文

问题

我正在寻找一种嘲笑我的KeyCloak服务的方法,称为userService。实际上,我只需要模拟isloggedin登录函数。我认为这不是一项艰巨的任务,但是经过几个小时的尝试,我仍然无法为此问题找到工作解决方案。

代码示例

uservice.js

import Keycloak from "keycloak-js";

const _kc = new Keycloak({
    url: "http://localhost:80",
    realm: "realmName",
    clientId: "clientName"
});

const initKeycloak = (onAuthenticatedCallback, onNotAuthenticatedCallback) => {
    _kc.init(
        {
            onLoad: 'check-sso',
            silentCheckSsoRedirectUri: window.location.origin + '/silent-check-sso.html',
            pkceMethod: 'S256',
            checkLoginIframe: false
        }
    )
        .then((authenticated) => {
            if (!authenticated) {
                console.error("user is not authenticated..!");
            }
            onAuthenticatedCallback();
        })
        .catch((error) => {
            onNotAuthenticatedCallback();
        })
};
const doLogin = _kc.login;

const doLogout = _kc.logout;

const getToken = () => {
    return _kc.token;
}

const isLoggedIn = () => {
    if (_kc.token) {
        return true;
    } else {
        return false;
    }
}

const updateToken = (successCallback) => {
    _kc.updateToken(5)
        .then(successCallback)
        .catch(doLogin);
}

const getUsername = () => _kc.tokenParsed?.preferred_username;

const hasRole = (roles) => {
    return roles.some((role) => _kc.hasRealmRole(role));
}

const UserService = {
    initKeycloak,
    doLogin,
    doLogout,
    isLoggedIn,
    getToken,
    updateToken,
    getUsername,
    hasRole,
};

export default UserService;

我已经尝试使用jest.mock()函数。因此,现在我可以无错误地推开loginbutton,但是AddButton仍然没有激活。

import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { BrowserRouter } from "react-router-dom";
import OrganizationsPage from "./OrganizationsPage";
import { act } from "react-test-renderer";

jest.mock("../Services/UserService", () => ({
    ...jest.requireActual("../Services/UserService"),
    doLogin: jest.fn(() => { return true }),
    isLoggedIn: jest.fn(() => { return true }),
}));

const MockedOrganizationsPage = () => {
    return (
        <BrowserRouter>
            <OrganizationsPage />
        </BrowserRouter>
    );
}

describe('OrganizationsPage Alter', () => {
    it('should activate alter buttons on login', async () => {

        // console.log(UserService.isLoggedIn())
        await act(async () => render(<MockedOrganizationsPage />))

        const loginButton = screen.getByText("Login");
        userEvent.click(loginButton);
        const addButton = screen.getByText("Add Organization");
        userEvent.click(addButton);
    })
})

Problem

I am looking for a way to mock my keycloak service called UserService. Actually I just need to mock the isLoggedIn and the login functions. I do not think this is a difficult task, but after some hours of trying I am still not able to get a working solution for this problem.

Code Samples

UserService.js

import Keycloak from "keycloak-js";

const _kc = new Keycloak({
    url: "http://localhost:80",
    realm: "realmName",
    clientId: "clientName"
});

const initKeycloak = (onAuthenticatedCallback, onNotAuthenticatedCallback) => {
    _kc.init(
        {
            onLoad: 'check-sso',
            silentCheckSsoRedirectUri: window.location.origin + '/silent-check-sso.html',
            pkceMethod: 'S256',
            checkLoginIframe: false
        }
    )
        .then((authenticated) => {
            if (!authenticated) {
                console.error("user is not authenticated..!");
            }
            onAuthenticatedCallback();
        })
        .catch((error) => {
            onNotAuthenticatedCallback();
        })
};
const doLogin = _kc.login;

const doLogout = _kc.logout;

const getToken = () => {
    return _kc.token;
}

const isLoggedIn = () => {
    if (_kc.token) {
        return true;
    } else {
        return false;
    }
}

const updateToken = (successCallback) => {
    _kc.updateToken(5)
        .then(successCallback)
        .catch(doLogin);
}

const getUsername = () => _kc.tokenParsed?.preferred_username;

const hasRole = (roles) => {
    return roles.some((role) => _kc.hasRealmRole(role));
}

const UserService = {
    initKeycloak,
    doLogin,
    doLogout,
    isLoggedIn,
    getToken,
    updateToken,
    getUsername,
    hasRole,
};

export default UserService;

I already tried to use the jest.mock() function. So now I can push the loginButton without an error, but the addButton still does not activate.

import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { BrowserRouter } from "react-router-dom";
import OrganizationsPage from "./OrganizationsPage";
import { act } from "react-test-renderer";

jest.mock("../Services/UserService", () => ({
    ...jest.requireActual("../Services/UserService"),
    doLogin: jest.fn(() => { return true }),
    isLoggedIn: jest.fn(() => { return true }),
}));

const MockedOrganizationsPage = () => {
    return (
        <BrowserRouter>
            <OrganizationsPage />
        </BrowserRouter>
    );
}

describe('OrganizationsPage Alter', () => {
    it('should activate alter buttons on login', async () => {

        // console.log(UserService.isLoggedIn())
        await act(async () => render(<MockedOrganizationsPage />))

        const loginButton = screen.getByText("Login");
        userEvent.click(loginButton);
        const addButton = screen.getByText("Add Organization");
        userEvent.click(addButton);
    })
})

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

小嗷兮 2025-02-18 03:01:29

因此,我找到了解决方案:

我不必模拟uservice.js文件,而是keycloak-js -module。为此,我创建了一个名为__模拟__的文件夹,然后放入模拟的模块中。开玩笑会自动知道从模拟文件夹而不是节点模块调用keycloak-js。

src/模拟/keycloak-js.js:

class Keycloak {
    token = "token available";
    url = null;
    realm = null;
    clientId = null;
    tokenParsed = {
        preferred_username: "dummy user",
    }

    constructor(keycloakConfig) {
        this.url = keycloakConfig.url;
        this.realm = keycloakConfig.realm;
        this.clientId = keycloakConfig.clientId;
    }

    login = () => {
        this.token = "Logged in";
    }

    logout = () => {
        this.token = null;
    }

    updateToken = () => {
        this.token = "Logged in";
        return new Promise((resolve, reject) => {
            if (!!this.token) {
                resolve();
            } else {
                reject();
            }
        })
    }

    init = (startupConfig) => {
        
    }

    hasRealmRole = (role) => {
        return true;
    }
}

export default Keycloak;


So I found the solution:

I do not have to mock the UserService.js file but more the keycloak-js-module. For this I create a folder called __mocks__ and put in my mocked module. Jest will automatically know to call keycloak-js from the mocks folder instead of node-modules.

src/mocks/keycloak-js.js:

class Keycloak {
    token = "token available";
    url = null;
    realm = null;
    clientId = null;
    tokenParsed = {
        preferred_username: "dummy user",
    }

    constructor(keycloakConfig) {
        this.url = keycloakConfig.url;
        this.realm = keycloakConfig.realm;
        this.clientId = keycloakConfig.clientId;
    }

    login = () => {
        this.token = "Logged in";
    }

    logout = () => {
        this.token = null;
    }

    updateToken = () => {
        this.token = "Logged in";
        return new Promise((resolve, reject) => {
            if (!!this.token) {
                resolve();
            } else {
                reject();
            }
        })
    }

    init = (startupConfig) => {
        
    }

    hasRealmRole = (role) => {
        return true;
    }
}

export default Keycloak;


~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文