Niedawno wdrożyliśmy usługę wiadomości w dużej mierze oparty na To rozwiązanie w kątach 7, ale obudowaliśmy wdrażanie testowania jednostki.

Mamy tę usługę:

@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();
  }
}

I mamy tę implementację, słuchanie wiadomości wysłanej przez inny komponent:

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

Chcemy mieć testować nasze wdrożenie, ale nie jesteśmy w stanie skobieć wysyłania i odbierania wiadomości. Próbujemy tego:

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();
});

Jesteśmy tam, ale utrata, czy ktoś może nam pomóc? Dzięki!

0
Ramon 20 luty 2019, 12:19

2 odpowiedzi

Najlepsza odpowiedź

Jeśli spojrzysz W Źródło zauważysz To, kiedy jest nazywany asObservable, nowy obiekt jest tworzony i zwrócony. Z tego powodu zasadniczo szpiegujesz niewłaściwy obiekt.

Możesz zabierać to z następującymi refaktorem:

@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$;
  }
}

I zaktualizuj swój test w następujący sposób:

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();
});
2
Jota.Toledo 20 luty 2019, 10:07

Jeśli Twoim celem jest po prostu udać wysyłanie / odbieranie wiadomości (usługę), możesz po prostu użyć makiety do usługi wiadomości.

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}]}
}....

Wtedy możesz po prostu przetestować swoje szpiedzy

expect(mockMessangerService.getMessage).toHaveBeenCalled();
expect(mockMessangerService.sendMessage).toHaveBeenCalledWith('Message');
1
Brendan B 23 styczeń 2020, 18:15