# Testing a hook with a state update - Fri 2nd Oct, 2020 I wanted to write some tests for my `useFilters` hook. This hook handles persisting selected filters to storage, fetchign them from storage, creating the query string for the feed query, and managing the filter Formik state. The main thing I wanted to test was the returned `filterParams` string, as this needs to be correct. First thing was to mock the storage library set and get methods: ```typescript= jest.mock('my-storage-lib', () => ({ get: jest.fn(), set: jest.fn().mockResolvedValue('Successfully saved'), })) ``` The next challenging part was that my hook uses a `useEffect` hook to fetch the persisted filters from storage and set back into Formik state. Since this state update is not "controlled" (ie. controlled by a prop like in [the hooks testing library example](https://github.com/testing-library/react-hooks-testing-library#usecountertestjs)), I would both get the dreaded `act` warning, and the `filterParams` value wasn't correct in the test. After some trial and error, this was the solution: ```typescript= jest.spyOn(myStorageLib, 'get').mockResolvedValue(JSON.stringify(mockInitialValues)) const { result, rerender } = renderHook(() => useFilters(), { wrapper: Wrapper }) await act(async () => { rerender(true) }) expect(result.current.filterParams).toBe(expected) ``` You need to wait for the hook to `renrender` asynchronously before calling your expect. ```typescript= test.each` case | myFilter | groups | customFilters | expected ${1} | ${null} | ${[]} | ${[]} | ${expected1} ${2} | ${myFilter} | ${[group]} | ${[customFilter]} | ${expected2} ${3} | ${myFilter} | ${[]} | ${[]} | ${expected3} ${4} | ${null} | ${[group]} | ${[customFilter]} | ${expected4} `('Case $case: it should return $expected', async ({ myFilter, groups, customFilters, expected }) => { jest.spyOn(RNSecureStorage, 'get').mockResolvedValue(JSON.stringify(mockInitialValues)) const { result, rerender } = renderHook(() => useFilters(), { wrapper: Wrapper }) await act(async () => { rerender(true) }) expect(result.current.filterParams).toBe(expected) }) ``` I also used the decent [react-native-collapsible](https://github.com/oblador/react-native-collapsible) instead of building my own accordion component for the filters. ###### tags: `programmingjournal` `2020` `C+` `filters` `hooks` `testing` `hookstesting` `mocks` `accordion`