reactjs 嘲笑zustand商店的笑话测试

gojuced7  于 2023-04-11  发布在  React
关注(0)|答案(1)|浏览(92)

呵呵,也许有人能帮我这个忙?我尝试用自定义值和动作来模拟一个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");
});

我很乐意在测试文件中进行模拟,而不是用几十个模拟商店污染我的系统......再次,这只是一个更大的应用程序的简化设置。

flseospp

flseospp1#

我遇到了同样的问题,我是这样解决的:
我使用的是React Native,所以我插入了Zustand的mock来重置每个测试的状态。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',
});

希望能帮上忙。

相关问题