Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing unit test for subscription inside onInit() in Angular

I have a Spinner Component class as below which would show/hide Progress Spinner using Angular material.

export class SpinnerComponent implements OnInit, OnDestroy {
    visible = true;
    private subscription: Subscription;

    constructor(private spinnerService: SpinnerService) {}

    ngOnInit() {
         this.subscription = this.spinnerService.spinnerState.subscribe((state: SpinnerState) => {
                this.visible = state.show;
           });
     }
    ngOnDestroy() {
         if (this.subscription) {
            this.subscription.unsubscribe();
         }
    }
}

How can I write a spec which could test for the specific line shown below which is inside the ngOnInit() method ?

this.visible = state.show;
like image 266
Chetan Khilare Avatar asked Mar 27 '18 16:03

Chetan Khilare


People also ask

How do you call Ngoninit in unit testing?

detectChanges(); }); it('should create', () => { expect(component). toBeTruthy(); }); }); Here, the fixture. detectChanges() is the method which will trigger OnInit in our component.

What is the function of fixture detectChanges () in Angular?

Fixtures have access to a debugElement , which will give you access to the internals of the component fixture. Change detection isn't done automatically, so you'll call detectChanges on a fixture to tell Angular to run change detection.

How do you mock a component in Angular unit testing?

A mock component in Angular tests can be created by MockComponent function. The mock component respects the interface of its original component, but all its methods are dummies. To create a mock component, simply pass its class into MockComponent function.

What is unit testing in angular?

Unit Testing is the practice of testing small lonely pieces of code to ensure it is bug-free. However, it is also called as Isolated testing. If our test code utilizes any external resource, like the database, network, etc., then it is not a unit test. Why do we use unit testing in Angular?

How to write tests for a service in angular?

That's fine for basic services, but if your service has dependencies, it's better to use the TestBed.configureTestingModule API like this: To get the service instance, we could inject it inside a test by calling TestBed.get () (with the service class as the argument). Well, with that you should be ready to write tests for your Angular applications.

What is default generated code for angular unit testing service example describe?

Default generated code for angular unit testing service example describe is a keyword from the jasmine framework, It is to specify logical separation for telling grouping of test cases. It contains beforeeach and it methods. beforeEach is used to initialize and declareall the dependencies and instances required for testcases defined in it methods.

How to fetch some data from an API using angular service?

I added some code to fetch some data from an API using an Angular service. So, here is how the modified app.component.ts file : Let’s write unit test for testing the method getPostDetails which calls service to get data. For unit testing the method, you need to mock the service method getPosts to test the component method.


Video Answer


1 Answers

First solution:

import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { SpinnerComponent } from './spinner.component';
import { of } from 'rxjs/observable/of';

describe('SpinnerComponent', () => {
  let component: SpinnerComponent;
  let fixture: ComponentFixture<SpinnerComponent>;
  const fakeSpinner = {
    spinnerState: of({ show: false }),
  };

  beforeEach(
    async(() => {
      TestBed.configureTestingModule({
        declarations: [SpinnerComponent],
        providers: [{ provide: SpinnerService, useValue: fakeSpinner }],
      }).compileComponents();
    }),
  );

  beforeEach(() => {
    fixture = TestBed.createComponent(SpinnerComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should set component.visible based on spinnerService state', () => {
    expect(component.visible).toEqual(false)
  });
});

The important thing to note is that we are providing our mock implementation of the spinner service.

Second solution:

The other way to test this would be to create a shallow test, without using Angular testing utilities at all. Since you do not care about the template interactions, you can also test this just like you would test regular ts classes.

class FakeSpinnerService {
  private spinnerStateSource = new Subject();
  spinnerState = this.spinnerStateSource.asObservable();

  emit(val: boolean) {
    this.spinnerStateSource.next({ show: val });
  }
}

it('should set component.visible based on spinnerService state', () => {
  const fakeService = new FakeSpinnerService();
  const component = new SpinnerComponent(fakeService as any);

  // initial value
  expect(component.visible).toBe(true);

  component.ngOnInit();

  fakeService.emit(false);
  expect(component.visible).toBe(false);

  fakeService.emit(true);
  expect(component.visible).toBe(true);
});
like image 82
Tomasz Kula Avatar answered Oct 17 '22 14:10

Tomasz Kula