0

Here is my chat service:

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

}

And here is what I've tried so far:

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

But it gives me the following error:

 Error: <spyOnProperty> : webSocket is not declared configurable

How to replace webSocket with a Subject so I can test it? RxJs: 6.5.5

Majesty
  • 2,097
  • 5
  • 24
  • 55

1 Answers1

1

It seems there is no good solution for this, there is a similar topic about fromEvent operator here: Error: <spyOn> : fromEvent is not declared writable or has no setter.

If the intention is to spy directly on the operator, then the only working option seems to be the targeting ES5, which I do not consider as a solution, because a deployed ES6+ could reduce the bundle size.

I guess the best option could be having a wrapper function for the webSocket operator. The wrapper function can already be spied upon. In your example the easyiest way would be setting up a spy for the getConnection() function, which has the responsibility of returning the connection instance.

Milan Tenk
  • 2,415
  • 1
  • 17
  • 24