typescript - Hogyan tudom kezelni a Zustand persist funkciót a Jest teszteimben?
Jelenleg egy React Native alkalmazást készítek, Zustandot használva az állapotkezelésemhez. A Zustand képes az állapotot tárolásba menteni, az én esetemben a React Native aszinkron tárolójába. Ez jól működik, azonban a tesztek futtatásakor a Zustand persist wrapper-je miatt a Jest tesztcsomagom megbukik.
Egyszerű részlet a Zustand állapotomból:
persist(
(set) => ({
variable: "something",
changeVariable: (variable: string) => {
set({ variable });
},
}),
{
name: "async-storage",
getStorage: () => AsyncStorage,
}
)
A tesztem:
describe("<SomeComponent />", () => {
it("renders default elements", () => {
const { getByText } = render(<SomeComponent />);
expect(getByText("Hello World")).toBeInTheDocument();
});
});
Ha kikommentezem a persist wrappert, a teszt lefut, ebben az állapotban azonban ezt a hibaüzenetet kapom
TypeError: Cannot read properties of undefined (reading 'bind')
14 | }
15 |
> 16 | export const useStore = create<ZustandState>()(
| ^
17 | persist(
18 | (set) => ({
Megpróbáltam az egész zustandot mockolni a https://docs.pmnd.rs/zustand/guides/testing használatával, de a kötési hiba csak a mockra kerül. Nem vagyok biztos benne, hogy maga a store undefined, és ezért nem engedi a kötést, vagy csak a persist okozza. Azonban nem tudom, hogyan kezeljem ezt. Bárkinek van ötlete, hogyan lehetne ezt megoldani?
Válasz #1
Szóval két napot töltöttem azzal, hogy megpróbáljak kitalálni egy hasonló problémát, szóval remélem, ez neked is működni fog.
Győződj meg róla, hogy a Zustand teszteket a dokumentációhoz hasonlóan állítod be, bár néhány módosítást kellett végrehajtanom annak érdekében, hogy a függvényeket helyesen tudjam exportálni.
A fő javítás akkor látható, amikor a reset függvényt hívjuk, létre kellett hoznom az inicializáló állapot egy mélyklónját. Majd készíteni egy másik mélyklónt abból, amikor a Zustand állapotát állítjuk. Rendkívül furcsa, de működik.
Referencia gyanánt a @react-native-async-storage/async-storage-t használjuk tartós tárolásként. Lehetséges, hogy ez befolyásolja.
Ne felejtsd el a node modulokat sem mock-olni, a fájlnak a __mocks__ mappában kell lennie, és ugyanúgy kell elnevezni, tehát zustand.ts
const { createStore: createStore } = jest.requireActual('zustand') as any;
export const storeResetFns = new Set<() => void>();
export const create = <S>(createState: StateCreator<S>) => {
return typeof createState === 'function' ? createInternalFn(createState) : createInternalFn;
};
export default create;
const createInternalFn = <S>(createState: StateCreator<S>) => {
const store = createStore(createState);
const initialState = _.cloneDeep(store.getState());
storeResetFns.add(() => {
/**
This is a hack to get around persisting
This might looks odd, it is. if you pass {initial state} to setState, then initial state gets updates to the current state...
*/
const t = _.cloneDeep(initialState)
if(initialState.trips) store.setState(t,true);
})
return store;
};
afterEach(() => {
//clear out state before each test
storeResetFns.forEach(fn => {
fn()
})
});
