1
resposta

[Dúvida] Mock spyOn não chama o 'next' do subscribe

Preciso de ajuda para entender o porque o mock spyOn não está chamando o next do subscribe.

Este é o teste:

import { HttpClientTestingModule } from '@angular/common/http/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { MessageService } from 'primeng/api';
import { of } from 'rxjs';
import { AuthService } from '../services/auth.service';

import { LoginComponent } from './login.component';

describe(LoginComponent.name, () => {
  let component: LoginComponent;
  let fixture: ComponentFixture<LoginComponent>;
  let service: AuthService;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [RouterTestingModule, HttpClientTestingModule],
      providers: [MessageService, AuthService],
    }).compileComponents();

    fixture = TestBed.createComponent(LoginComponent);
    component = fixture.componentInstance;
    service = TestBed.inject(AuthService);

    // Simula a resposta bem-sucedida do serviço utilizando o mock
    spyOn(service, 'login').and.returnValue(
      of({
        accessToken: {
          name: 'API-teste',
          abilities: ['*'],
          id: 1,
          user: {
            id: 1,
            nome: 'Teste',
            nome_usuario: 'teste',
            email: 'teste@teste.com',
          },
        },
        plainTextToken: '1|teste',
      })
    );

    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it(`#${LoginComponent.prototype.login.name} deve processar sucesso`, () => {
    spyOn(component, 'processarSucesso');

    // Preencha o formulário com dados válidos antes de chamar o método login
    component.loginForm.controls['email'].setValue('teste@teste.com');
    component.loginForm.controls['password'].setValue('teste123456');

    component.login();

    expect(component.processarSucesso).toHaveBeenCalled();
  });
});

Este é o erro do teste:

Expected spy processarSucesso to have been called.

Este é o relatório do coverage:

Insira aqui a descrição dessa imagem para ajudar na acessibilidade

Como pode ser visto no coverage, o next na linha 74 do componente não é chamado. Já tentei todas as formas que é ensinado no curso e não consegui chamar esse bendito next.

1 resposta

Salve, Valdomiro!

Depois compartilha o seu repositório porque isso ajuda a gente na hora de entender o problema :)

Baseado no que você mostrou, vamos ao caso:

Se o método login retorna um Observable, então você precisa se inscrever nesse Observable para garantir que ele tenha concluído antes de verificar se o spy foi chamado.

O spyOn por si só não irá acionar a execução do Observable. Você precisa explicitamente se inscrever nele.

Aqui está um exemplo de como você pode fazer isso no seu teste:

it(`#${LoginComponent.prototype.login.name} deve processar sucesso`, (done) => {
  spyOn(component, 'processarSucesso');

  // Preencha o formulário com dados válidos antes de chamar o método login
  component.loginForm.controls['email'].setValue('teste@teste.com');
  component.loginForm.controls['password'].setValue('teste123456');

  component.login().subscribe(() => {
    expect(component.processarSucesso).toHaveBeenCalled();
    done();
  });
});

Nesse código, eu modifiquei o teste para se inscrever no Observable retornado pelo método login. A função done é chamada dentro do callback subscribe para garantir que o expect seja chamado apenas depois que o Observable for concluído.

Isso deve garantir que o Observable tenha concluído e que o spy tenha sido chamado no momento em que o expect for executado.