简体   繁体   English

Angular,主题单元测试

[英]Angular, Subjects Unit Testing

We have recently implemented a message service largely based on this solution in Angular 7, but we are stucked on the unit testing implementation.我们最近在 Angular 7 中主要基于这个解决方案实现了一个消息服务,但我们坚持单元测试实现。

We have this service:我们有这样的服务:

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

And we have this implemetation, listening for a message sent by another component:我们有这个实现,监听另一个组件发送的消息:

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

We want to unit test our implementation, but we are not able to mock the sending and receiving of the message.我们想对我们的实现进行单元测试,但我们无法模拟消息的发送和接收。 We are trying this:我们正在尝试这个:

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

We are a but lost there, could any one please help us?我们在那里迷路了,有人可以帮助我们吗? Thanks!谢谢!

If you look at the source youll notice that whenever asObservable is called, a new object is created and returned.如果您查看源代码,您会注意到每当asObservable被调用时,都会创建并返回一个新对象。 Because of that, you are basically spying on the wrong object.因此,您基本上是在监视错误的对象。

You can takle this with the following refactoring:您可以通过以下重构来解决这个问题:

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

And update your test as follows:并按如下方式更新您的测试:

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

If your goal is to just mock the sending/receiving of the message (your service), you can just use a mock for the message service.如果您的目标只是模拟消息(您的服务)的发送/接收,您可以只对消息服务使用模拟。

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

Then you can just test your spies然后你可以测试你的间谍

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM