Reputation: 441
I have an Angular 5 app that uses NgRx Effects. One of the Effects handles Signup to a website by passing data entered by the user to a NodeJS Backend. The Effect works exactly as intended but when I try to unit test it with Marbles, I get a weird error.
This is the Effect:
@Effect()
authSignup$ = this.actions$
.ofType(AuthActions.TRY_SIGNUP)
.switchMap((signUpData: {
first_name: string,
last_name: string,
username: string,
password: string,
type: string,
agreement: boolean
}) =>
this.httpClient.post(
'/custom-endpoint',
{
first_name: signUpData.first_name,
last_name: signUpData.last_name,
username: signUpData.username,
password: signUpData.password,
type: signUpData.type,
agreement: signUpData.agreement
},
{
headers: new HttpHeaders({
'Content-Type': 'application/json'
})
})
.map((res) => {
return new AuthActions.SuccessfulSignup();
})
.catch((error: {reason: string}) => {
return Observable.of(new AuthActions.UnsuccessfulSignup({reason: error.reason}))
})
);
This is the Unit Test with Marbles. It follows Todd Motto's guidelines for testing NgRx Effects.
export class TestActions extends Actions {
constructor() {
super(empty());
}
set stream(source: Observable<any>) {
this.source = source;
}
}
export function getTestActions() {
return new TestActions();
}
fdescribe('AuthEffects', () => {
let actions$: TestActions;
let effects: fromEffects.AuthEffects;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
CookieModule.forRoot(),
StoreModule.forRoot({...fromGlobal.reducers}),
RouterTestingModule,
HttpClientTestingModule
],
providers: [
fromEffects.AuthEffects,
CookieAesService,
{ provide: Actions, useFactory: getTestActions },
],
});
actions$ = TestBed.get(Actions);
effects = TestBed.get(fromEffects.AuthEffects);
});
it('should attempt to Sign Up the user', () => {
const trySignup = new fromActions.TrySignup({
first_name: 'test',
last_name: 'test',
password: 'test',
username: '[email protected]',
type: 'test',
agreement: false
});
const unsuccessfulSignup = new fromActions.UnsuccessfulSignup({ reason: 'test' });
actions$.stream = hot('a', { a: trySignup });
const expected = cold('b', { b: unsuccessfulSignup });
expect(effects.authSignup$).toBeObservable(expected);
});
});
Finally, this is the error I get in Karma:
Expected $.length = 0 to equal 1.
Expected $[0] = undefined to equal Object({ frame: 0, notification: Notification({ kind: 'N', value: UnsuccessfulSignup({ payload: Object({ reason: 'test' }), type: 'UNSUCCESSFUL_SIGNUP' }), error: undefined, hasValue: true }) }).
I deduce from this rather cryptic error message that the trySignup
action was fired, but not the unsuccessfulSignup
action. Does anyone know why this might be happening?
Thanks!
Upvotes: 1
Views: 1917
Reputation: 50
Alex,
Your switchMap switches the stream over to the http.post
stream, which you are not stubbing or returning. You need to emit an error from the HttpClientTestingModule
first for the catch
event to fire.
See the link below for an example:
Upvotes: 1