Недавно мы реализовали службу сообщений, в значительной степени основанную на это решение в 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();
});
Мы заблудились там, может ли кто-нибудь помочь нам? Спасибо!





Если вы посмотрите у источника, вы заметите, что всякий раз, когда вызывается 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();
});
@Ramon Да, это потому, что ваши исходные тестовые примеры слишком поздно устанавливают шпиона. Обновлено
Если ваша цель состоит в том, чтобы просто издеваться над отправкой/получением сообщения (ваш сервис), вы можете просто использовать макет для службы сообщений.
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');
Спасибо! Тем не менее, у нас все еще есть сообщение об ошибке jasmine: «Ошибка: была вызвана ожидаемая подписка на шпиона».