Katharine Osborne
Katharine Osborne

Reputation: 7031

How to mock an Angular subscription in Jasmine test

I'm trying to fix a unit test (I'm not particularly familiar with Jasmine), after adding some subscriptions to a service. I'm getting an error saying that they are undefined. I'm not sure how to properly include the subscriptions.

My component (there's more to it than this but I've shortened for clarity):

export class AppComponent implements OnInit, AfterViewInit {
  isSignedIn = false;
  isLoggedIn = false;
  signedInSubscription: Subscription;
  loggedInSubscription: Subscription;

  constructor(
    private authenticationService: AuthenticationService,
    private router: Router,
    private http403Tester: Http403TestService,
  ) {
    this.isLoggedIn = authenticationService.isLoggedIn;
    this.isSignedIn = authenticationService.isSignedIn;
    this.setEnvironment();
  }

  async ngOnInit() {
    // line 69 below, this is where the error is
    this.signedInSubscription = this.authenticationService.observableIsSignedIn.subscribe(item => {
      this.isSignedIn = item;
    });
    this.loggedInSubscription = this.authenticationService.observableIsLoggedIn.subscribe(item => {
      this.isLoggedIn = item;
    });
  }  
}

The service:

export class AuthenticationService {
  constructor() {
    this.observableIsSignedIn = new BehaviorSubject<boolean>(this.isSignedIn);
    this.observableIsLoggedIn = new BehaviorSubject<boolean>(this.isLoggedIn);
  }

  isSignedIn: boolean = null;
  isLoggedIn: boolean = null;
  observableIsSignedIn: any;
  observableIsLoggedIn: any;

The spec:

describe('AppComponent', () => {
  let authenticationService: any;
  let http403Tester: any;
  let router: any;
  let component: AppComponent;

beforeEach(() => {
  authenticationService = {
    isSignedIn: jasmine.createSpy(),
    isLoggedIn: jasmine.createSpy(),
    observableIsSignedIn: jasmine.createSpy(),
    observableIsLoggedIn: jasmine.createSpy(),
  };
  router = { navigateByUrl: jasmine.createSpy() };
  http403Tester = { isAuthenticated: jasmine.createSpy() };
  component = new AppComponent(authenticationService, router, http403Tester);
});

describe('ngOnInit()', () => {
  it('should navigate to /unauthorised when a 403 status code is returned', async () => {
  // Arrange
  http403Tester.isAuthenticated.and.returnValue(false);

  // Act
  await component.ngOnInit();

  // Assert
  expect(router.navigateByUrl).toHaveBeenCalledWith('/unauthorised');
});

And the error:

TypeError: Cannot read property 'subscribe' of undefined
at AppComponent.<anonymous> (src/app/app.component.ts:69:83)

So I'm pretty sure that createSpy() is the incorrect way to mock a subscription:

observableIsSignedIn: jasmine.createSpy()

But I have no idea how to proceed or what to search for. Any ideas?

Upvotes: 2

Views: 2470

Answers (1)

Ramesh Rajendran
Ramesh Rajendran

Reputation: 38663

Try this

 authenticationService = {
    isSignedIn: jasmine.createSpy(),
    isLoggedIn: jasmine.createSpy(),
    observableIsSignedIn: new BehaviorSubject<boolean>(undefined).asObservable(),
    observableIsLoggedIn:  new BehaviorSubject<boolean>(undefined).asObservable(),
  };

For more details : Mocking a BehaviourSubject in a component test spec

Update:

Actually you have missed the proper configuration for unit testing. please check : https://angular.io/guide/testing#component-dom-testing

Upvotes: 2

Related Questions