I want to unit test functional effect as described here
export const loadUsers = createEffect(
(actions$ = inject(Actions), usersService = inject(UsersService)) => {
return actions$.pipe(
ofType(userActions.getUser),
exhaustMap(() => {
return usersService.getAll().pipe(
map((users) => userActions.usersLoadedSuccess({ users })),
);
})
);
},
{ functional: true }
);
https://ngrx.io/api/effects/createEffect#functional-effects
How one would unit test this functional effect. Kindly note there is no injectable or class
I am expecting a way to test this functional effect. I tried below approach but the effect is not getting triggered at all.
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { Observable, of } from 'rxjs';
import { TestBed } from '@angular/core/testing';
import { provideMockActions } from '@ngrx/effects/testing';
import { MockProvider } from 'ng-mocks';
import { Actions } from '@ngrx/effects';
import { userActions } from './user-store';
import { MockStore, provideMockStore } from '@ngrx/store/testing';
import { UsersService } from './users.service';
import { loadUsers } from './user.effects';
describe('Offer Effects', () => {
let actions$: Observable<unknown>;
let store: MockStore;
let userService: UsersService;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [loadUsers, MockProvider(UsersService), provideMockStore(), provideMockActions(() => actions$)],
});
actions$ = TestBed.inject(Actions);
store = TestBed.inject(MockStore);
userService = TestBed.inject(UsersService);
});
it('should test load users effect', async () => {
actions$ = of({
type: userActions.getUser,
});
const users = { name: 'Test', surname: 'Data' };
jest.spyOn(userService, 'getAll').mockReturnValue(of(users));
const spy = jest.spyOn(userActions, 'usersLoadedSuccess');
await loadUsers;
expect(spy).toHaveBeenCalledWith({ users });
});
});
If you want to use await
, you're not actually calling the effect, so do something like:
await loadUsers(actions$, userService);
Otherwise use subscribe
like in the 'Testing' example here: https://github.com/ngrx/platform/issues/3668
it('loads users successfully', () => {
usersEffects.loadUsers(actionsMock, usersServiceMock).subscribe((action) => {
expect(serviceMock, 'getAll').toHaveBeenCalled();
expect(action).toEqual(/* ... */);
});
});