AngularユニットテストでサブスクライブするモックサービスのSubjectプロパティをモックする

Jan 19 2021

私のAngularユニットテストでは、モックサービスには2つのプロパティがあります。

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

現在、モックサービスからプロパティをモックするために次の2つのアプローチを使用しようとしています。

  • Angular Unit Test Mock Replay Subject
  • Jasmineを使用して(メソッドではなく)値プロパティをスパイする方法

Riht今私のテストは次のようになります:

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

なぜそれが私にはうまくいかないのですか?エラーが発生しました:

未定義のプロパティ「サブスクライブ」を読み取れません

回答

1 satanTime Jan 19 2021 at 13:37

ので、それは仕事をしない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;

その後、それは機能するはずです、多分小さな調整が必要です。


痛みを避けるために、そのような場合にはモックライブラリを使用することをお勧めします。

たとえば、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.
  });
}
1 bakunet Jan 19 2021 at 14:29

私はアプローチに行き着きました、そこで私はこのような模擬サービスを注入します:

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