🚀[FEATURE]: How to mock dispatch
See original GitHub issueHi, I’m creating unit tests and have a problem when testing actions. I would like to mock dispatch
function in a way it really dispatches only a tested action and any additional dispatch call are only spied.
Something like this:
it('should login with valid credentials', async (done) => {
const action = new Login(validCredentials)
const dispatchSpy = spyOn(store, 'dispatch').withArgs(action).and.callThrough()
store.dispatch(action)
await expect(store.selectSnapshot(AuthState.getError)).toBeFalsy()
await expect(store.selectSnapshot(AuthState.getPending)).toBeTruthy()
authTrigger.next()
const dispatchedLoginSuccessAction = [].concat(...dispatchSpy.calls.allArgs()).find(a => a instanceof LoginSuccess)
await expect(dispatchedLoginSuccessAction).toBeTruthy()
await expect(dispatchedLoginSuccessAction.payload).toEqual(token)
})
BUT! This doesn’t work, because as I investigate, the store.dispatch
is different from the dispatch
function in the action context. I know I can use the construction like this without mocking (and it works):
actions$.pipe(ofActionDispatched(LoginSuccess)).subscribe(async (action) => {
await expect(action).toBeTruthy()
done()
})
BUT! I don’t want to actually dispatch additional actions because of side effects. Consider the tested action dispatches an action from another module, so I would have to mock all services which causes side effects in that module.
I’ve found out the actual dispatch to be mocked is the one in the InternalStateOperations
object, but I don’t know how to mock it.
QUESTION So what is the proper way to make tests like this?
Issue Analytics
- State:
- Created 4 years ago
- Reactions:3
- Comments:13 (5 by maintainers)
Here is a code snippet of a utility that I like to use for capturing actions that have been dispatched in my tests. Hope this helps!
You can either add it to your imports (
NgxsActionCollector.collectActions()
) to start collecting actions from NGXS initialisation. Or you can just inject it from theTestBed
and callstart()
,stop()
andreset()
as needed.Example usage in the doc comments in the code.
As much as I love using NGXS, this seems to be a major downside. The catch of using redux state management should be the simplicity of testing. However, not being able to test dispatched actions from another action in a straight-forward way goes directly against this advantage.