Angular, предметное модульное тестирование

Недавно мы реализовали службу сообщений, в значительной степени основанную на это решение в Angular 7, но мы застряли на реализации модульного тестирования.

У нас есть такая услуга:

@Injectable()
export class MessageService {
  private subject = new Subject<any>();
  sendMessage(message: MessageInput) {
    this.subject.next(message);
  }
  clearMessage() {
    this.subject.next();
  }
  getMessage(): Observable<any> {
    return this.subject.asObservable();
  }
}

И у нас есть эта реализация, прослушивающая сообщение, отправленное другим компонентом:

ngOnInit() {
this.subscription = this.messageService.getMessage().subscribe(
  (message: MessageInput) => {
    if (message) {
      .....
    }
  }, () => {
      .....
  }
)};

Мы хотим протестировать нашу реализацию, но не можем имитировать отправку и получение сообщения. Мы пытаемся это:

beforeEach(() => {
  TestBed.configureTestingModule({
    schemas: [NO_ERRORS_SCHEMA],
    declarations: [...],
    providers: [
      ...
      MessageService
    ],
    imports: [...]
  });
  fixture = TestBed.createComponent(...);
  component = fixture.componentInstance;
  fixture.detectChanges();
});

it('makes ngOnInit expected calls', () => {
  const messageService: MessageService = fixture.debugElement.injector.get(
    MessageService
  );
  component.ngOnInit();
  expect(component.subscription).toBeDefined();
  const message: MessageInput = {text: TypeMessage...., data: '...'};
  const nextSpy = spyOn(messageService.getMessage(), 'subscribe');
  messageService.sendMessage(message);
  expect(nextSpy).toHaveBeenCalled();
});

Мы заблудились там, может ли кто-нибудь помочь нам? Спасибо!

Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
0
0
3 437
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Если вы посмотрите у источника, вы заметите, что всякий раз, когда вызывается asObservable, создается и возвращается новый объект. Из-за этого вы в основном шпионите не за тем объектом.

Вы можете решить это с помощью следующего рефакторинга:

@Injectable()
export class MessageService {
  private subject = new Subject<any>();
  public readonly messages$ = this.subject.asObservable();

  sendMessage(message: MessageInput) {
    this.subject.next(message);
  }
  clearMessage() {
    this.subject.next();
  }
  getMessage(): Observable<any> {
    return this.messages$;
  }
}

И обновите свой тест следующим образом:

it('makes ngOnInit expected calls', () => {
  const messageService: MessageService = fixture.debugElement.injector.get(MessageService);
  const nextSpy = spyOn(messageService.messages$, 'subscribe');

  component.ngOnInit();
  messageService.sendMessage(message); 

  expect(component.subscription).toBeDefined();
  expect(nextSpy).toHaveBeenCalled();
});

Спасибо! Тем не менее, у нас все еще есть сообщение об ошибке jasmine: «Ошибка: была вызвана ожидаемая подписка на шпиона».

Ramon 20.02.2019 10:59

@Ramon Да, это потому, что ваши исходные тестовые примеры слишком поздно устанавливают шпиона. Обновлено

Jota.Toledo 20.02.2019 11:07

Если ваша цель состоит в том, чтобы просто издеваться над отправкой/получением сообщения (ваш сервис), вы можете просто использовать макет для службы сообщений.

mockSubject = new Subject();
mockSubject =next({'Message'})

mockMessangerService= {
 getMessage:  jasmine.createSpy('openConfirmModal').and.returnValue(mockSubject.asObservable()),
 sendMessage: jasmine.createSpy('sendMessage')
}

TestBed.configureTestingModule({
 ...
 }).overrideComponent(*component*,
{   
  set: { providers: [{provide: MessageService , useValue: mockMessangerService}]}
}....

Тогда вы можете просто проверить своих шпионов

expect(mockMessangerService.getMessage).toHaveBeenCalled();
expect(mockMessangerService.sendMessage).toHaveBeenCalledWith('Message');

Другие вопросы по теме