首页 > 解决方案 > 是否有一个 Jest 函数来禁止任何其他函数调用而不是预期的?

问题描述

我知道您可以模拟和监视函数内部的函数调用,例如使用 jest.spyOn 和 jest.fn() ... .toHaveBeenCalledTimes(1) 等。在 Spock 框架测试中,您可以使用:

0 * _ // 不允许任何其他交互

有没有办法通过 Jest 实现这一目标?

例子:

export default class Service {

    public startAllWorkers(): void {
        const processClient: ProcessClient = new ProcessClient();
        const processMonitor: ProcessMonitor = new ProcessMonitor();
        const defaultValue: number = 10;

        processClient.runClient(defaultValue);
        processMonitor.runMonitor('pling')
    }

}

describe('Service test', () => {

    let service: Service;

    beforeEach(() => {
        service = new Service();
        ProcessClient.prototype.runClient = jest.fn()
        ProcessMonitor.prototype.runMonitor = jest.fn()
    });

    it('should only call specific methods', () => {
        const spyService = jest.spyOn(service, 'startAllWorkers');

        service.startAllWorkers();

        expect(spyService).toHaveBeenCalledTimes(1);
        expect(ProcessClient.prototype.runClient).toHaveBeenCalledTimes(1);
        expect(ProcessMonitor.prototype.runMonitor).toHaveBeenCalledTimes(1);
        // expect no other interactions inside service method
    });

})

标签: typescriptunit-testingmockingjestjs

解决方案


Jest spy 功能相对温和。toBeCalledWith断言允许检查是否使用指定的参数进行了调用之一。

需要明确声明更具体的调用:

// fn('foo', 1);
// fn('bar', 2);
expect(mockFn).toBeCalledTimes(2); // redundant but provides human readable output
expect(mockFn.mock.calls).toEqual([
  ['foo', 1]
  ['bar', expect.any(Number)]
]);

如果一个函数没有被连续调用,可以简短地断言一个间谍不允许意外调用:

// fn('foo', 1);
expect(mockFn).toBeCalledTimes(1);
expect(mockFn).toBeCalledWith('foo', 1);
mockFn.mockClear();
...
// fn('bar', 2);
expect(mockFn).toBeCalledTimes(1);
expect(mockFn).toBeCalledWith('bar', 2);
mockFn.mockClear();
...
expect(mockFn).not.toBeCalled();

或者,智能间谍可以负责实现和预期用途:

mockFn.mockImplementation((...args) => {
  // first call
  if (mockFn.mock.calls.length === 1) {
    expect(args).toEqual(...);
    return ...;
  }

  // second call
  if (mockFn.mock.calls.length === 2) {
    expect(args).toEqual(...);
    return ...;
  }

  // no more calls
  expect(mockFn.mock.calls.length).not.toBe(3);
});

推荐阅读