呵呵,也许有人能帮我这个忙?我尝试用自定义值和动作来模拟一个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");
仍然会有“mocked foo”作为值,尽管mocked foo_set
会被调用(例如,添加控制台日志会被记录)。但是同样,foo
的值不会被更新。
但是,如果我将store mocking部分移动到它自己的文件中并将其导入到我的测试中,一切都将按预期工作。
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;
更新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");
});
我很乐意在测试文件中进行模拟,而不是用几十个模拟商店污染我的系统......再次,这只是一个更大的应用程序的简化设置。
1条答案
按热度按时间flseospp1#
我遇到了同样的问题,我是这样解决的:
我使用的是React Native,所以我插入了Zustand的mock来重置每个测试的状态。https://docs.pmnd.rs/zustand/guides/testing
我在存储中创建了一个名为_mock的操作,它接收一个对象并将其插入到存储中。
模拟动作:
模拟操作类型:
使用方法:
希望能帮上忙。