嘿,也许有人能帮我一下?我尝试用自定义值和操作来模拟一个zustand存储。我想在我的测试文件中进行模拟。但我失败得很惨
这是我的react应用程序的一个简化示例。
component.jsx
import React from "react";
import useStore from "@app/component_store";
export default function Component() {
const foo = useStore((state) => state.foo);
const setFoo = useStore((state) => state.foo_set);
return (
<>
<div data-testid="foo">{foo}</div>
<button data-testid="btn-foo" onClick={() => setFoo("new foo")}>
set foo
</button>
</>
);
}
component_store.jsx
import create from "zustand";
const useStore = create((set) => ({
foo: "foo",
foo_set: (value) => set(() => ({ foo: value })),
}));
export default useStore;
component.test.jsx
/* global afterEach, expect, jest, test */
import React from "react";
import { cleanup, fireEvent, render } from "@testing-library/react";
import "@testing-library/jest-dom";
import mockCreate from "zustand";
import Component from "@app/component";
jest.mock("@app/component_store", () => (args) => {
const useStore = mockCreate((set, get) => ({
foo: "mocked foo",
foo_set: (value) => set(() => ({ foo: "mocked set foo" })),
}));
return useStore(args);
});
afterEach(cleanup);
test("override store values and actions", () => {
const { container, getByTestId } = render(<Component />);
const foo = getByTestId("foo");
const btnFoo = getByTestId("btn-foo");
expect(foo.textContent).toBe("mocked foo");
fireEvent.click(btnFoo);
expect(foo.textContent).toBe("mocked set foo");
});
这个失败。expect(foo.textContent).toBe("mocked set foo");
仍将拥有"模拟食物"。作为一个值,尽管模拟的foo_set
被调用(例如,添加控制台日志确实被记录)。但同样,foo
的值不会更新。
但是,如果我将存储模拟部分移到它自己的文件中,并将其导入到我的测试中,那么一切都会如预期的那样工作。
component_store_mocked.jsx
注意:这与component.test.jsx
中的相同import create from "zustand";
const useStore = create((set, get) => ({
foo: "mocked foo",
foo_set: (value) => set(() => ({ foo: "mocked set foo" })),
}));
export default useStore;
<<p>更新strong> component.test.jsx/* global afterEach, expect, jest, test */
import React from "react";
import { cleanup, fireEvent, render } from "@testing-library/react";
import "@testing-library/jest-dom";
import mockCreate from "zustand";
import Component from "@app/component";
// this part here
import mockComponentStore from "@app/component_store_mocked";
jest.mock("@app/component_store", () => (args) => {
const useStore = mockComponentStore;
return useStore(args);
});
afterEach(cleanup);
test("override store values and actions", () => {
const { container, getByTestId } = render(<Component />);
const foo = getByTestId("foo");
const btnFoo = getByTestId("btn-foo");
expect(foo.textContent).toBe("mocked foo");
fireEvent.click(btnFoo);
expect(foo.textContent).toBe("mocked set foo");
});
我想在测试文件中做模拟,而不是用几十个模拟存储来污染我的系统。同样,这只是一个更大的应用程序的简化设置。
我也遇到过同样的问题,我是这样解决的:
我使用React Native,所以我插入了Zustand的模拟来重置每个测试的状态。https://docs.pmnd.rs/zustand/guides/testing
我在存储库中创建了一个名为_mock的操作,该操作接收对象并将其插入到存储库中。
模拟行动:
_mock(store) {
set({
state: { ...get().state, ...store },
actions: get().actions,
});
},
模拟动作类型:
_mock: (store: Partial<RootStateAuth>) => void;
用法:
useAuthStore.getState().actions._mock({
role: 'purchases',
registrationCompleted: false,
name: 'Fulano',
});
我希望这对你有帮助。
您可以使用jest mock模拟测试中从存储返回的数据。
当你在函数中调用UseWhateverStore时,你检索了一个函数,它将状态作为参数传递,然后当你说state时。如果它从store返回那个状态。
下面是一个模拟 的例子jest.mock("../stores/accounts-store.ts", () => ({
useAccountsStore: (passedFunction: any) => {
const data = {
createNewAccount: jest.fn(),
getFactions: jest.fn(),
factions: []
}
return passedFunction(data);
}
}));