0

SpyOn is used to detect the parameters passed to an underlying function. In some cases we want to modify the result from the call-through and return that to the caller.

How do we get the result of of the call-through in SpyOn before it is returned?

Here is an example:

import {INestApplication} from '@nestjs/common';
import {Test} from '@nestjs/testing';
import {CommonModule} from '@src/common/common.module';
import {Repository} from 'typeorm';
import {User} from '@src/database/entity/user.entity';

describe('AuthService', () => {
    let service: AuthService;
    let app: INestApplication;
    let repo: Repository<User>;

    beforeEach(async () => {
        const module = await Test.createTestingModule({
            imports: [CommonModule],
            providers: [AuthService, {provide: 'USER_REPOSITORY',
                        useValue: mockRepositoryUser()},
           ]}).compile();

        app = module.createNestApplication();
        await app.init();

        service = module.get<AuthService>(AuthService);
        repo = module.get('USER_REPOSITORY');
    });  

    it('test passthrough ', async () => {

        const sp = jest.spyOn(repo , 'findOne').mockImplementation(async (args) => {
           // here we want to first call the original FindOne function 
           // and get the result and then modify that 
           // result and return it. 

           const result  = await originalRepo.findOne(args)  <= ???     
           result.user = {name: 'david'};
           return result;
        );

        service.doWork();
        expect(sp).toHaveBeenCalledTimes(2); 
    });
});

Of course in the mockImplementation I can return any value. But let's say I don't want to statically return a value and just want to use the underlying database to get some result and then modify it. Since I have already mocked the entire store with some valid data every time I call the findOne I get valid results. But in order to test the failure cases I want to modify the returned results from the call-through.

I hope that is clear.

4

1 回答 1

1

好吧,看起来你不能。要知道的关键是 jest.spyOn 只是基本 jest.fn() 用法的糖。我们可以通过存储原始实现、将模拟实现设置为原始并稍后重新分配原始实现来实现相同的目标:

import * as app from "./app";
import * as math from "./math";

test("calls math.add", () => {
  // store the original implementation
  const originalAdd = math.add;

  // mock add with the original implementation
  math.add = jest.fn(originalAdd);

  // spy the calls to add
  expect(app.doAdd(1, 2)).toEqual(3);
  expect(math.add).toHaveBeenCalledWith(1, 2);

  // override the implementation
  math.add.mockImplementation(() => "mock");
  expect(app.doAdd(1, 2)).toEqual("mock");
  expect(math.add).toHaveBeenCalledWith(1, 2);

  // restore the original implementation
  math.add = originalAdd;
  expect(app.doAdd(1, 2)).toEqual(3);
});

当我们可以有条件地从模拟返回不同的值时, https://github.com/facebook/jest/issues/6180将解决对此的需求。

于 2020-06-10T16:24:19.707 回答