How to unit test MatSnackbar using Jasmine Karma in Angular
Asked Answered
D

1

3

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", "", );
         })
Delve answered 11/7, 2021 at 8:30 Comment(7)
If you want to just test the snack bar and not the entire method I would say to create a mock/stub authService with a stubbed submitnominYellow method that will return a success. You’ll want to use a fakeAsync test callback in the “it” test method. You can create a spy of the snackBar and its create method. Hope this helpsOrlandoorlanta
Thanks but snackbar is part of the function, so how will I proceed. Please guide me I am new to the jasmine karma unit testing.Delve
Is this.snackBar a viewChild of component or what?Orlandoorlanta
I am not understanding what you're trying to say. Please answer in the form of code.Delve
` Hitesh Agashe` may you please provide a piece of code where you declare snackBar property?Homeopathy
Edited sir, please check!Delve
@Homeopathy Gentle reminderDelve
H
2

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});
})
Homeopathy answered 21/7, 2021 at 12:8 Comment(13)
can we chat in person? my code is too long to comment and I can't edit original question.Delve
Error: <toHaveBeenCalledWith> : Expected a spy, but got Object({ open: spy on unknown.open }). Usage: expect(<spyObj>).toHaveBeenCalledWith(...arguments)Delve
sorry, I missed a thing. Changed expect(mockSnackbarMock) to expect(mockSnackbarMock.open)Homeopathy
and sorry, chat in person would be too much of distractionHomeopathy
Expected spy unknown.open to have been called with: [ 'Submitted Successfully', '' ] but it was never called.Delve
You skipped the part: after all the actions which trigger the snack bar. I don't know how would you prefer to do it. You can consider emulating click on a button that triggers the snackbar or maybe just calling the method.Homeopathy
Onsubmit function triggers snackbar and I am already calling itDelve
The expectation error message states that the snackbar.open method was not called. Is there a chance that this.auth.submitnominYellow(newYellow) doesn't return a proper observable in the test?Homeopathy
Mock is returning the proper value, i checked. Should I add something in unit test case code??Delve
it would be useful to show the unit test code (:Homeopathy
Unit test code added in question, please proceed.Delve
I see the mock for the auth service is const MockAuthService = {submitnominYellow:(id) => ({ success: true })};. With such mock, during the test run the piece this.auth.submitnominYellow(newYellow).subscribe would be the equal to true and one should see an error ` true is not a function`. something doesn't match in that code. see how to setup a mock properly here: https://mcmap.net/q/510275/-how-to-mock-a-observable-stream-while-testing-angular2-componentsHomeopathy
Yup, submitnominYellow:(id) => of (mockopblue),Delve

© 2022 - 2024 — McMap. All rights reserved.