简体   繁体   English

Mocking 在 Angular 单元测试中订阅的模拟服务的主题属性

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

In my Angular unit testing my mocked service has two properties:在我的 Angular 单元测试中,我的模拟服务有两个属性:

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

And in my SUT I use them in my constructor:在我的 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);
    });

Right now I am trying to use these 2 approaches to mock properties from mocked service:现在我正在尝试使用这两种方法来模拟来自模拟服务的属性:

Riht now my testing looks like this:现在我的测试看起来像这样:

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

So in the test I create:所以在我创建的测试中:

  • service mock hubServiceMock ,服务模拟hubServiceMock ,

  • fake messageChange = new Subject();messageChange = new Subject(); , ,

  • fake gameChange = new Subject();gameChange = new Subject(); , ,

  • i run for both .next ,我为两个.next竞选,

  • and I setup spy for properties:我为属性设置了间谍:

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

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

Why it does not work to me?为什么它对我不起作用? I receive an error:我收到一个错误:

Cannot read property 'subscribe' of undefined无法读取未定义的属性“订阅”

It doesn't work because hubServiceMock doesn't have the fake subjects in its messageChange and gameChange , you need to set them before calling new SignalRService(hubServiceMock) .它不起作用,因为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;

then it should work, maybe small adjustments are needed.那么它应该可以工作,也许需要进行一些小的调整。


I would suggest to use a mocking lib for such cases to avoid pain.我建议在这种情况下使用 mocking lib 以避免疼痛。

For example with ng-mocks , the test might look like:例如使用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.
  });
}

I ended up with approach, where I inject mocked service like this:我最终采用了方法,在其中注入了这样的模拟服务:

hubServiceMock = TestBed.inject(HubConnectionService);

Then I mock my Subject s like this:然后我像这样模拟我的Subject

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

And in other tests I can use methods of mocked service like that:在其他测试中,我可以使用这样的模拟服务方法:

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

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

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