开玩笑模拟toHaveBeenCalledWith期望不同的参数

时间:2019-06-26 11:25:44

标签: node.js typescript jestjs nestjs

我正在TripService中测试此功能:

async createAndMapTrips<T extends ITripEntity>(
        driver: DriverEntity,
        entities: T[],
        intervalInMinutes: number = 10,
    ): Promise<[TripEntity[], T[]]> {
        const trips: TripEntity[] = [];

        const [tripsDb] = await this.tripRepository.getAndCountTrips(driver, {
            driverId: driver.driverId,
            fromEndTime: moment.utc(entities[0].timestamp).subtract(intervalInMinutes, 'minutes').toISOString(),
            toEndTime: moment.utc(entities[entities.length - 1].timestamp).add(intervalInMinutes, 'minutes').toISOString(),
        });

        this.logger.log(tripsDb);

        return [
            trips,
            entities.map((entity: T, idx: number) => {
                let trip: TripEntity = this.findLastTripWithinRangeFromEntity(trips, entity);
                if (!trip) {
                    trip = this.findLastTripWithinRangeFromEntity(tripsDb, entity);
                    if (!trip) {
                        this.logger.log('Trip does not exist, creating new trip');
                        trip = this.tripRepository.create({
                            driver,
                            id: this.generateRandomTripId(),
                            startTime: moment.utc(entity.timestamp).toISOString(),
                            endTime: moment.utc(entity.timestamp).toISOString(),
                        });
                    }
                    trips.push(trip);
                }
                trip.endTime = moment.utc(entity.timestamp).toISOString();
                entity.trip = trip;
                return entity;
            }),
        ];
    }

    private findLastTripWithinRangeFromEntity<T extends ITripEntity>(trips: TripEntity[], entity: T, intervalInMinutes: number = 10): TripEntity {
        return findLast(
            trips,
            ((t: TripEntity) =>
                moment.utc(entity.timestamp).isSameOrAfter(moment.utc(t.startTime), 'milliseconds')
                && moment.utc(entity.timestamp).diff(moment.utc(t.endTime), 'minutes') <= intervalInMinutes),
        );
    }

这是我的测试

describe('TripService.createAndMapTrips()', () => {
    const entities: ITripEntity[] = [
      { timestamp: '2019-05-07T11:10:00.000Z', trip: null },
    ];

    const driver: DriverEntity = plainToClass(DriverEntity, {
      id: 1,
      driverId: 'one',
      clientId: 'one',
    });

    const tripsDb: TripEntity[] = plainToClass(TripEntity, [
      { id: '1', startTime: '2019-05-07T10:50:00.000Z', endTime: '2019-05-07T11:01:00.000Z' },
      // this should be selected as it is the last one according to time
      { id: '2', startTime: '2019-05-07T10:55:00.000Z', endTime: '2019-05-07T11:06:00.000Z' },
    ]);

    const result: [TripEntity[], ITripEntity[]] = [
      plainToClass(TripEntity, [
        { id: '2', startTime: '2019-05-07T10:55:00.000Z', endTime: '2019-05-07T11:10:00.000Z' },
      ]),
      [{
        timestamp: '2019-05-07T11:10:00.000Z', trip: plainToClass(TripEntity, {
          id: '2',
          startTime: '2019-05-07T10:55:00.000Z',
          endTime: '2019-05-07T11:10:00.000Z',
        }),
      }],
    ];

    it('should map existing trips if the trips already exist within the time range requested', async () => {
      tripRepositoryMock.getAndCountTrips.mockReturnValue([[tripsDb], 2]);

      const findLastTripWithinRangeFromEntity = jest.spyOn(TripService.prototype as any, 'findLastTripWithinRangeFromEntity');

      findLastTripWithinRangeFromEntity
        .mockReturnValue(plainToClass(TripEntity, {
          id: '2',
          startTime: '2019-05-07T10:55:00.000Z',
          endTime: '2019-05-07T11:06:00.000Z',
        }))
        .mockReturnValueOnce(undefined);

      await expect(service.createAndMapTrips(driver, entities)).resolves.toEqual(result);
      expect(tripRepositoryMock.getAndCountTrips).toHaveBeenCalledTimes(1);
      expect(tripRepositoryMock.getAndCountTrips).toHaveBeenCalledWith(driver, {
        driverId: driver.driverId,
        fromEndTime: moment.utc(entities[0].timestamp).subtract(10, 'minutes').toISOString(),
        toEndTime: moment.utc(entities[entities.length - 1].timestamp).add(10, 'minutes').toISOString(),
      });
      expect(findLastTripWithinRangeFromEntity).toHaveBeenCalledTimes(2);
      expect(findLastTripWithinRangeFromEntity).toHaveBeenNthCalledWith(1, [], entities[0]);
      expect(findLastTripWithinRangeFromEntity).toHaveBeenNthCalledWith(2, tripsDb, entities[0]);
      expect(findLastTripWithinRangeFromEntity).toHaveBeenCalledWith([], entities[0]);

      expect(tripRepositoryMock.create).toHaveBeenCalledTimes(0);
    });
});

我遇到以下错误:

 ● TripService › TripService.createAndMapTrips() › should map existing trips if the trips already exist within the time range requested

    expect(jest.fn()).toHaveBeenNthCalledWith(expected)

    Expected mock function first call to have been called with:
      []
    as argument 1, but it was called with
      [{"endTime": "2019-05-07T11:10:00.000Z", "id": "2", "startTime": "2019-05-07T10:55:00.000Z"}].

    Difference:

    - Expected
    + Received

    - Array []
    + Array [
    +   TripEntity {
    +     "endTime": "2019-05-07T11:10:00.000Z",
    +     "id": "2",
    +     "startTime": "2019-05-07T10:55:00.000Z",
    +   },
    + ]

      415 |       });
      416 |       expect(findLastTripWithinRangeFromEntity).toHaveBeenCalledTimes(2);
    > 417 |       expect(findLastTripWithinRangeFromEntity).toHaveBeenNthCalledWith(1, [], entities[0]);
          |                                                 ^
      418 |       expect(findLastTripWithinRangeFromEntity).toHaveBeenNthCalledWith(2, tripsDb, entities[0]);
      419 |       expect(findLastTripWithinRangeFromEntity).toHaveBeenCalledWith([], entities[0]);
      420 |

      at Object.<anonymous> (trip/trip.service.spec.ts:417:49)
      at fulfilled (trip/trip.service.spec.ts:4:58)

我显然是在设置模拟返回值,并且根据逻辑,对findLastTripWithinRangeFromEntity的第一次调用应该使用[]进行,而第二次调用tripsDb进行调用,但是调用时会使用不同的方法值。

我似乎找不到原因。

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

不能100%确定这一点,但是我认为这与how the jest.spyOn method calls the function有关。出于某种原因,它可能两次都与对象一起调用它,但同样,并不是100%确定。