angularunit-testingjestjskarma-jasmineangular-unit-test

How to unit test MatSnackbar using Jasmine Karma in Angular


I want to perform unit testing on this onSubmit function where the positive submission is leading to MatSnackbar with message, "Submitted Successfully". I am new to Jasmine Karma please guide me about the testing of MatSnackbar in this case.

Component.ts

import { MatSnackBar } from "@angular/material/snack-bar";

  constructor(
    private snackBar: MatSnackBar,
    private auth: AuthenticateService,

  ) {}
...
...
  onSubmit(e) {
    const newYellow = {
      G1: e.value.Yellow_G1,
      G2: e.value.Yellow_G2,
      G3: e.value.Yellow_G3,
      G4: e.value.Yellow_G4,
      B1: e.value.Yellow_B1,
      B2: e.value.Yellow_B2,
      B3: e.value.Yellow_B3,
      B4: e.value.Yellow_B4,
    };
    console.log(newYellow);
    this.auth.submitnominYellow(newYellow).subscribe(
      (res) => {
        console.log(res);
        this.snackBar.open("Submitted Successfully", "", {
          duration: 2000,
        });
      },
      (error) => {
        console.log(error);
      }
    );
  }

This is code for submitnomin function. auth.service.ts

submitnominYellow(inpobj) {
    console.log(inpobj);
    return this.http.post(environment.apiUrl + '/api/customize/yellow', inpobj);
}

My unit test case is somewhat like this.
component.spec.ts

    const mockSnackbarMock = jasmine.createSpyObj(['open']);
    mockSnackbarMock.open
    
    const mockopblue =
      {
        success: true
    }
    
    const MockAuthService = {
      submitnominYellow:(id) => (mockopblue),
      getuser:() => (undefined)
    
    };
...
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ YellowCustomizeComponent ],
      imports: [HttpClientTestingModule, MatSnackBarModule, FormsModule, RouterTestingModule],
      providers:[{provide: MatSnackBar, useValue: mockSnackbarMock},
      {provide: AuthenticateService, useValue: MockAuthService}
      ]

    })
    .compileComponents();
  }));
...

          fit('should open the snack bar with correct arguments when form submitted', () => {
            const e =  {
              value:{
                Yellow_G1: "YGirlName1",
                Yellow_G2: "GirlName2",
                Yellow_G3: "GirlName3",
                Yellow_G4: "GirlName4",
                Yellow_B1: "BoyName1",
                Yellow_B2: "BoyName2",
                Yellow_B3: "BoyName3",
                Yellow_B4: "BoyName4",
              }
              
            };
            component.onSubmit(e)
            console.log('mockSnackbarMock',mockSnackbarMock)
            // console.log('yellow onsubmit',component.onSubmit(e)); 
            expect(mockSnackbarMock.open).toHaveBeenCalledWith("Submitted Successfully", "", );
         })

Solution

  • in the test, it is possible to change the dependency injection configuration so that instead of the SnackBar instance the mock would be provided. That is how to do it:

    const mockSnackbarMock = jasmine.createSpyObj(['open']);
    mockSnackbarMock.open
    
    await TestBed.configureTestingModule({
                declarations: [
                    ...
                ],
                providers: [
                    {provide: MatSnackBar, useValue: mockSnackbarMock},
                ],
                imports: [
                    ...
                ],
            }).compileComponents();
    

    Later on in the test after all the actions which trigger the snack bar, you can check if the open method was called correctly:

    it('should open the snack bar with correct arguments when form submitted', () => {
       //emulate submission
    
       expect(mockSnackbarMock.open).toHaveBeenCalledWith("Submitted Successfully", "", {duration: 2000});
    })