การเยาะเย้ยคุณสมบัติหัวเรื่องของบริการจำลองที่จะสมัครในการทดสอบหน่วยเชิงมุม

Jan 19 2021

ในหน่วยเชิงมุมของฉันการทดสอบบริการจำลองของฉันมีคุณสมบัติสองประการ:

  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
  • วิธีการสอดแนมบนทรัพย์สินมูลค่า (แทนที่จะเป็นวิธีการ) ด้วยจัสมิน

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ไม่ได้มีวิชาปลอมของตนmessageChangeและคุณจะต้องตั้งพวกเขาก่อนที่จะเรียกgameChangenew SignalRService(hubServiceMock)

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

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

จากนั้นควรใช้งานได้อาจจำเป็นต้องมีการปรับเปลี่ยนเล็กน้อย


ฉันขอแนะนำให้ใช้ 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.
  });
}
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);