【问题标题】:Angular & Jest: Why is the subscribe block running inside ngOnInit?Angular & Jest:为什么订阅块在 ngOnInit 中运行?
【发布时间】:2020-12-17 23:20:06
【问题描述】:

我试图开玩笑地运行一个简单的测试:setUsername() 方法在joinGameService 上被调用。但是当我运行测试时,出现以下错误:

game.component.ts:

import { Component, OnInit } from '@angular/core';
import { GameService } from './shared/services/game.service';
import { JoinGameService } from './shared/services/join-game.service';
import { MatDialog } from '@angular/material/dialog';
import { QuitGameDialogComponent } from './shared/components/quit-game-dialog/quit-game-dialog.component';

@Component({
  selector: 'app-game',
  templateUrl: './game.component.html',
  styleUrls: ['./game.component.css']
})
export class GameComponent implements OnInit {

  public playersInLobby: Array<any>;

  constructor(
    public gameService: GameService,
    public dialog: MatDialog,
    private joinGameService: JoinGameService,
  ) { }

  ngOnInit() {
    this.joinGameService.onSetUsername()
      .subscribe((data: any) => {
        const { users } = data.room;
        this.playersInLobby = users;
      });
  }

  public enterRoom(userAndRoomId: any): void {
    const { username, roomId } = userAndRoomId;
    this.clientUsername = username;
    this.roomIsJoined = true;
    this.roomId = roomId;
    this.joinGameService.setUsername(roomId, username);
  }
}

join-game.service.ts里面的相关方法:

  public setUsername(roomId: string, username: string): void {
    this.socket.emit('set-username', {
      roomId,
      username
    });
  }

  public onSetUsername(): Observable<any> {
    return this.socket.fromEvent('set-username');
  }

game.component.spec.ts:

import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { GameComponent } from './game.component';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { JoinGameService } from './shared/services/join-game.service';
import { GameService } from './shared/services/game.service';
import { of } from 'rxjs';
import { MatDialogModule } from '@angular/material/dialog';

describe('GameComponent', () => {
  let component: GameComponent;
  let fixture: ComponentFixture<GameComponent>;
  let MOCK_USERNAME_AND_ID;

  const mockJoinGameService = {
    setUsername: jest.fn(),
    onSetUsername: jest.fn().mockReturnValue(of({data: 'test'})),
    isHost: jest.fn().mockReturnValue(of({data: 'test'})),
  };
  const mockGameService = {
    onStartGame: jest.fn().mockReturnValue(of({data: 'test'})),
  };

  beforeEach(waitForAsync(() => {
    TestBed.configureTestingModule({
      imports: [
        MatDialogModule,
      ],
      declarations: [
        GameComponent
      ],
      providers: [
        { provide: GameService, useValue: mockGameService },
        { provide: JoinGameService, useValue: mockJoinGameService },
        { provide: ToastrService, useValue: mockToastrService }
      ],
      schemas: [ NO_ERRORS_SCHEMA ]
    })
      .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(GameComponent);
    component = fixture.componentInstance;
  });

  it('should create', () => {
    fixture.detectChanges();
    expect(component).toBeTruthy();
  });

  describe('enterRoom', () => {
    beforeEach(() => {
      MOCK_USERNAME_AND_ID = {
        username: 'James',
        roomId: 'a1b2c3d4'
      };
      fixture.detectChanges();
    });

    test('should call the setUsername method in joinGameService', () => {
      component.enterRoom(MOCK_USERNAME_AND_ID);
      expect(mockJoinGameService.setUsername).toHaveBeenCalled();
    });
  });
});

为什么订阅块在onSetUsername 上运行,这在本次测试中甚至不相关?

【问题讨论】:

    标签: angular testing jestjs


    【解决方案1】:

    您的测试设置使用字符串“test”填充data 对象,但您的ngOnInit() 订阅逻辑期望该对象具有room 属性。

    相关建议:通过使用更强的类型来利用 TypeScript。那些anys 隐藏了编译器可以轻松捕获的错误。

    【讨论】:

    • 哦,我刚刚经历了一个巨大的 D'oh 时刻!我假设因为订阅块内的代码只会在onSetUsername 收到来自服务器的消息时触发(与这个问题完全无关),所以该代码应该只有然后运行。谢谢!
    猜你喜欢
    • 2018-06-12
    • 2019-01-25
    • 2020-02-12
    • 1970-01-01
    • 2017-06-09
    • 2022-07-31
    • 2019-04-16
    • 2021-06-22
    • 1970-01-01
    相关资源
    最近更新 更多