簡體   English   中英

Mocking 在 Angular 單元測試中訂閱的模擬服務的主題屬性

[英]Mocking a Subject property of mocked service to be subscribed in the Angular unit test

在我的 Angular 單元測試中,我的模擬服務有兩個屬性:

  public messageChange: Subject<ChatMessage> = new Subject<ChatMessage>();
  public gameChange: Subject<GameState> = new Subject<GameState>();

在我的 SUT 中,我在構造函數中使用它們:

this._subChat = this.hub.messageChange.subscribe((message: ChatMessage) => {
      this.message = message;
      this.messageChange.next(this.message);
    });
    this._subGame = this.hub.gameChange.subscribe((game: GameState) => {
      this.game.setGame(game);
    });

現在我正在嘗試使用這兩種方法來模擬來自模擬服務的屬性:

現在我的測試看起來像這樣:

describe('SignalRService', () => {
  let signalrService: SignalRService;
  const hubServiceMock = jasmine.createSpyObj('HubConnectionService', [
    'isConnectionStarted',
  ]);
  const messageChange = new Subject();
  const gameChange = new Subject();

  beforeEach(() => {
    signalrService = new SignalRService(
      hubServiceMock
    );
    let msg = {} as ChatMessage;
    let gam = {} as GameState;
    messageChange.next(msg);
    gameChange.next(gam);
  });

  it('Service_ShouldBeCreated', () => {
    spyOnProperty(hubServiceMock, 'messageChange', 'get').and.returnValue(
      messageChange
    );
    spyOnProperty(hubServiceMock, 'gameChange', 'get').and.returnValue(
      gameChange
    );
    expect(signalrService).toBeTruthy();
  });
}

所以在我創建的測試中:

  • 服務模擬hubServiceMock ,

  • messageChange = new Subject(); ,

  • gameChange = new Subject(); ,

  • 我為兩個.next競選,

  • 我為屬性設置了間諜:

    spyOnProperty(hubServiceMock, 'messageChange', 'get').and.returnValue( messageChange );

    spyOnProperty(hubServiceMock, 'gameChange', 'get').and.returnValue( gameChange );

為什么它對我不起作用? 我收到一個錯誤:

無法讀取未定義的屬性“訂閱”

它不起作用,因為hubServiceMock在其messageChangegameChange中沒有虛假主題,您需要在調用new SignalRService(hubServiceMock)之前設置它們。

  const hubServiceMock = jasmine.createSpyObj('HubConnectionService', [
    'isConnectionStarted',
  ]);
  const messageChange = new Subject();
  const gameChange = new Subject();

  // add this
  hubServiceMock.messageChange = messageChange;
  hubServiceMock.gameChange = gameChange;

那么它應該可以工作,也許需要進行一些小的調整。


我建議在這種情況下使用 mocking lib 以避免疼痛。

例如使用ng-mocks ,測試可能如下所示:

describe('SignalRService', () => {
  beforeEach(() => MockBuilder(SignalRService, ITS_MODULE));

  const hubServiceMock = {
    messageChange: new Subject(),
    gameChange: new Subject(),
  };
  beforeEach(() => MockInstance(HubConnectionService, hubServiceMock));


  it('Service_ShouldBeCreated', () => {
    const signalrService = MockRender(SignalRService).point.componentInstance;
    expect(signalrService).toBeTruthy();

    hubServiceMock.messageChange.next({});
    hubServiceMock.gameChange.next({});
    // next assertions.
  });
}

我最終采用了方法,在其中注入了這樣的模擬服務:

hubServiceMock = TestBed.inject(HubConnectionService);

然后我像這樣模擬我的Subject

it('Service_ShouldBeCreated', () => {
    spyOn(hubServiceMock.messageChange, 'next');
    spyOn(hubServiceMock.gameChange, 'next');
    expect(signalrService).toBeTruthy();
  });

在其他測試中,我可以使用這樣的模擬服務方法:

let spyIsConnectionStarted = spyOn(hubServiceMock, 'isConnectionStarted');
    spyIsConnectionStarted.and.returnValue(true);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM