Шпионить за методом, переданным в модуль с поддельным узлом - PullRequest
0 голосов
/ 27 сентября 2018

Я создаю клиент, который обернет библиотеку SignalR:

export class RealTimeCommunicator {

  /** SignalR hub connection */
  private hubConnection: HubConnection | null = null;

  private buildConnection(url: string): HubConnection {
    return new HubConnectionBuilder()
    .withUrl(url)
    .build();
  }

  public subscribe(onStart: () => void, success: (data: IVehicleInfo) => void, fail?: (err: Error) => void): () => void {
    this.hubConnection = this.buildConnection("/someurl");
    this.hubConnection.on("send", data => {
      success(data);
    });

    this.hubConnection.start()
      .then(onStart)
      .catch(err => fail && fail(err));

    return this.unsubscribe;
  }

  public subscribeToVehicleDetails(vehicleId: number, success: (data: IVehicleInfo) => void, fail?: (err: Error) => void): () => void {
    return this.subscribe(() => this.hubConnection!.invoke("EnrolInVehicleGroupAsync", vehicleId), success, fail);
  }

Я хочу протестировать ее, но макет SignalR, поэтому я добавил __mocks__/@aspnet/signalr.ts к решению:

let SignalR = jest.genMockFromModule("@aspnet/signalr");

class HubConnection {

  public on(methodName: string, callback: () => string): Promise<void> {
    this.successCallback = callback;
    return Promise.resolve()
  }

  public start(): Promise<void> { return Promise.resolve() }

  public successCallback: () => string = () => "failure";
}

let hubConnection = new HubConnection();

let HubConnectionBuilder = () => ({
  withUrl: (url) => ({
    build: () => hubConnection
  })
});

SignalR = {
  HubConnectionBuilder: HubConnectionBuilder,
  HubConnection: hubConnection
};

module.exports = SignalR;

Я пытаюсь шпионить за методом on, чтобы убедиться, что он был вызван, и в качестве дополнительной цели подтвердите, что мой обработчик успеха был зарегистрирован правильно.

import { RealTimeCommunicator } from "./RealTimeCommunicator";
jest.mock('SignalR');

describe("RTC", () => {
  test("foo", () => {
    const ConnectionBuilder = require("SignalR").HubConnectionBuilder;

    const connection = new ConnectionBuilder().withUrl("").build();

    const spy = jest.spyOn(connection, 'on');
    expect(spy).toHaveBeenCalled();  //Expectation fails
    const successText = "success!";
    const successCallBack: () => string = () => successText;
    const rtc = new RealTimeCommunicator();

    rtc.subscribeToVehicleDetails(1, successCallBack, _ => _);
    expect(connection.successCallback()).toBe(successText); // connection.successCallback is undefined
  })
});

Если яПоместите контрольные точки в мой SignalR макет, я вижу, что вызывается on, но шпион не видит его.Также successCallback, который я прикрутил к моей шутке, возвращается как undefined

Ответы [ 2 ]

0 голосов
/ 07 октября 2018

Вы близки, вам просто нужно два изменения.


Вернуть результат success(data):

public subscribe(onStart: () => void, success: (data: IVehicleInfo) => void, fail?: (err: Error) => void): () => void {
  this.hubConnection = this.buildConnection("/someurl");
  this.hubConnection.on("send", data => {
    return success(data);   // return the result
  });

  this.hubConnection.start()
    .then(onStart)
    .catch(err => fail && fail(err));

  return this.unsubscribe;
}

Подождите, чтобы подтвердить, что spyбыл вызван до после вы звоните rtc.subscribeToVehicleDetails:

const spy = jest.spyOn(connection, 'on');
const successText = "success!";
const successCallBack: () => string = () => successText;
const rtc = new RealTimeCommunicator();

rtc.subscribeToVehicleDetails(1, successCallBack, _ => _);
expect(spy).toHaveBeenCalled();   // SUCCESS
expect(connection.successCallback()).toBe(successText);   // SUCCESS
0 голосов
/ 06 октября 2018

Можете ли вы предоставить какой-либо рабочий образец (например, в форме репо) для воспроизведения вашей проблемы?Насколько я вижу, в предоставленных фрагментах кода есть некоторые недостатки.

Прежде всего, почему jest.mock('SignalR'); действительно работает? SignalR не является модулем, который должен выдавать ошибку.Вы должны смоделировать модуль, который вы фактически импортируете: jest.mock('@aspnet/signalr');.Кроме того, ваша первая часть теста состоит из тестирования сторонней библиотеки - зачем вы вообще это делаете, кроме проверки работоспособности вашего макета?

Во-вторых, вы проверяете, если on метод был вызван мгновенно после создания шпиона.Хотя шпион регистрирует только звонки, сделанные после его создания.Возможно, вы захотите сделать метод on шпионом по умолчанию:

// in __mocks__/@aspnet/signalr.ts

class HubConnection {

  public on = jest.fn().mockImplementation((methodName: string, callback: () => string) => {
    this.successCallback = callback;
    return Promise.resolve()
  });


  // ...

}

В-третьих, соединение , которое вы создаете в тесте, другое.от того, который вы создадите позже при использовании subscribeToVehicleDetails , поэтому successCallback все равно будет возвращать «сбой», если он будет работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...