Home > Net >  Cypress spy no being called
Cypress spy no being called

Time:02-03

I'm trying to create a simple Cypress test that tests whether a service method was called. Here is my test setup:

const accountService = {
   logout: () => {
      return null;
   }
}
beforeEach(() => {
   cy.mount(ToolbarComponent, {
      imports: [
         MatDialogModule,
         MatMenuModule,
         MatToolbarModule,
         MatButtonModule,
         BrowserAnimationsModule,
         MatIconModule
     ],
     declarations: [ToolbarComponent],
     providers: [{provide: AccountService, useValue: accountService}]
  });
});

describe('logout method', () => {
     it('should call the account service logout method', () => {
         cy.spy(accountService, 'logout').as('accountService-logout-method');
         cy.get(elementBindings.userMenuButton).click();
         cy.wait(1000);
         cy.get(elementBindings.logoutButton).should('be.visible'); // THIS PASSES
         cy.get(elementBindings.logoutButton).click();
         expect(accountService.logout).to.be.called; 
     });
});

This is the relevant html:

<button
  data-cy="open-user-menu-button"
  mat-icon-button
  
  aria-label="Example icon-button with heart icon"
  [matMenuTriggerFor]="menu">
  <mat-icon>person</mat-icon>
</button>
<mat-menu #menu="matMenu">
  <button mat-menu-item>Edit Profile</button>
  <button data-cy='logout-button' *ngIf="loggedOnUser$ | async" mat-menu-item (click)="logout()">Logout</button>
</mat-menu>

This is the logout() method in the component.ts file:

logout() {    
   this.accountService.logout();
}

The last expect statement: expect(accountService.logout).to.be.called; is failing and I cannot understand why? The expect() statement to verify the button is visible passes and I can physically see the button is there in Cypress before the click() method is called on it.

Any ideas why this might be happening?

CodePudding user response:

So the main reason you're likely having an issue is because Cypress is asynchronous. So using the expect() outside of a then() or should() callback won't work since you have to wait for the Cypress commands to complete.

I see you already have an alias on your spy, so to assert a spy:

// Instead of this
expect(accountService.logout).to.be.called;

// Get the alias, then use should() to assert
cy.get('@accountService-logout-method').should('have.been.called');

// or 
cy.get('@accountService-logout-method').should((spy) => {
  expect(spy).to.be.called;
});

Your entire test would look something like this:

// Entire test
it('should call the account service logout method', () => {
  cy.spy(accountService, 'logout').as('accountService-logout-method');
  cy.get(elementBindings.userMenuButton).click();
  cy.wait(1000);
  cy.get(elementBindings.logoutButton).should('be.visible'); // THIS PASSES
  cy.get(elementBindings.logoutButton).click();

  cy.get('@accountService-logout-method').should('have.been.called');
});

  • Related