Testing
Unit Test - Mocking Reducer Providers hooks
- Useful when testing custom hooks.
- Useful when using enzyme
shallow.- No need for
SyncReducerProvidernorAsyncReducerProvider.
- No need for
Mocking useReducer:
- With traditional & sensational Jasmine:
import * as ReducerProviderModule from 'react-reducer-provider'
..
const mockState = {}
const mockDispatcher = jasmine.createSpy()
spyOn(ReducerProviderModule, 'useReducer')
.and
.returnValue([
mockState,
mockDispatcher
])
or
if values is going to change from test case to test case:
import * as ReducerProviderModule from 'react-reducer-provider'
..
let mockState
let mockDispatcher
spyOn(ReducerProviderModule, 'useReducer')
.and
.callFake(() => [
mockState,
mockDispatcher
])
- With Jest:
const mockState = {}
const mockDispatcher = jest.fn()
jest.mock('react-reducer-provider', () => ({
useReducer: () => ([
mockState,
mockDispatcher
])
}))
Mocking useReducerState:
- With traditional & sensational Jasmine:
import * as ReducerProviderModule from 'react-reducer-provider'
..
const mockState = {}
spyOn(NamedReducerModule, 'useReducerState')
.and
.returnValue(mockState)
or
if state is going to change from test case to test case:
import * as ReducerProviderModule from 'react-reducer-provider'
..
let mockState
spyOn(ReducerProviderModule, 'useReducerState')
.and
.callFake(() => mockState)
- With Jest:
const mockState = {}
jest.mock('react-reducer-provider', () => ({
useReducerState: () => mockState
}))
Mocking useReducerDispatcher:
- With traditional & sensational Jasmine:
import * as ReducerProviderModule from 'react-reducer-provider'
..
const mockDispatcher = jasmine.createSpy()
spyOn(ReducerProviderModule, 'useReducerDispatcher')
.and
.returnValue(mockDispatcher)
or
if dispatcher is going to change from test case to test case:
import * as ReducerProviderModule from 'react-reducer-provider'
..
let mockDispatcher
spyOn(ReducerProviderModule, 'useReducerDispatcher')
.and
.callFake(() => mockDispatcher)
- With Jest:
const mockDispatcher = jest.fn()
jest.mock('react-reducer-provider', () => ({
useReducerDispatcher: () => mockDispatcher
}))
Examples can be seen at: MockingReducerProvider.test.jsx.
Integration Test - Testing how a component that requires to be enclosed in a Reducer Provider behave
1 . Use enzyme mount.
2 . Enclosed component with a SyncReducerProvider or AsyncReducerProvider:
- add the required properties:
id: identifier of the context used by the component to be test.initialState: the state required by the test.reducer: the reducer required by the test.
it('test description', () => {
const component = mount(
<SyncReducerProvider
id='theContextName'
initialState=
reducer={(prevState, action) => {
switch (action) {
case 'ACTION1':
return {
field1: valueA,
fieldN: valueB,
}
default:
return prevState
}
}}
>
<ComponentToBeTest />
</SyncReducerProvider>
)
Examples can be seen at: SingletonReducerProvider.test.jsx, SyncReducerProvider.test.jsx and AsyncReducerProviderWithAsync.test.jsx.
Asynchronous testing
When a Component make an asynchronous call to the reducer (or some React hook) inside an useEffect then use act for testing, e.g.
import { useReducer } from 'react-reducer-provider'
export function SomeComponent() {
const [ state, dispatch ] = useReducer()
React.useEffect(() => {
asyncCall().then(() => dispatch('Some'))
}, [])
..
import { act } from 'react-dom/test-utils'
it('should render SomeComponent', async () => {
await act(async () => {
const main = mount(
<AsyncReducerProvider reducer={() => {/*..*/} } initialState={someValue}>
<SomeComponent/>
</AsyncReducerProvider>
)
expect(main.contains(/* .. */)).toBe(true)
})
})