如何在 Jasmine 中模拟 rxjs webSocket?

Posted

技术标签:

【中文标题】如何在 Jasmine 中模拟 rxjs webSocket?【英文标题】:How to mock rxjs webSocket in Jasmine? 【发布时间】:2021-08-25 09:45:47 【问题描述】:

这是我的聊天服务:

import webSocket, WebSocketSubject from 'rxjs/webSocket';
import delayWhen, retryWhen, take from 'rxjs/operators';
import timer from 'rxjs';

...

export class ChatConnectionService 

  private readonly _connection: WebSocketSubject<any>;
  public readonly messages$: Observable<ChatInboundMessage>;

  constructor() 
    this._connection = this.getConnection();
    this.messages$ = this._connection.asObservable();
  

  private getConnection(): WebSocketSubject<any> 
    return webSocket(`.../chat`);
  


这是我迄今为止尝试过的:

import * as rxJsWebSocket from 'rxjs/webSocket';

describe('ChatConnectionService', () => 
  let service: ChatConnectionService;

  const subject = new Subject();
  let webSocketSpy;

  beforeEach(() =>    
    webSocketSpy = spyOnProperty(rxJsWebSocket, 'webSocket', 'get').and.returnValue(<any>subject);

    service = new ChatConnectionService();
  );

  it('should create a new connection when service instantiated', () => 
    expect(webSocketSpy).toHaveBeenCalledTimes(1);
  );
);

但它给了我以下错误:

 Error: <spyOnProperty> : webSocket is not declared configurable

如何将webSocket 替换为主题以便我可以测试它? RxJs:6.5.5

【问题讨论】:

【参考方案1】:

这个好像没有什么好的解决办法,这里有一个关于fromEvent操作符的类似话题: Error: <spyOn> : fromEvent is not declared writable or has no setter.

如果打算直接监视操作员,那么唯一可行的选择似乎是目标ES5,我不认为这是一种解决方案,因为部署的ES6+ 可以减少包大小。

我想最好的选择可能是为webSocket 运算符提供一个包装函数。包装器功能已经可以被窥探。在您的示例中,最简单的方法是为 getConnection() 函数设置一个间谍,该函数负责返回连接实例。

【讨论】:

以上是关于如何在 Jasmine 中模拟 rxjs webSocket?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用jasmine-marbles测试rxjs管道中的timeout()

RXjs使用jasmine进行6次回调测试

如何提供一个Rxjs observable作为使用Jasmine中的combineLatest的方法的数据

如何为combineLatest rxjs Angular编写Jasmine Unit测试用例

如何使用 Angular 和 Jasmine 模拟 socket.io

如何模拟在 AngularJS Jasmine 单元测试中返回承诺的服务?