Jestjs无法模拟嵌套的局部函数

时间:2018-05-16 20:46:24

标签: jestjs

我有一个难题,试图让手动模拟使用一些本地代码。基本上有一个与异步资源交互的组件(在本例中为lowdb)。现在我可以从lowdb模拟我正在使用的所有函数,但是这个函数的输出实际上非常简单,我宁愿只是模拟那个调用。但是,我正在构建的测试不会直接调用此函数。

这可能不太清楚,所以这里有一个例子(这是我想要模拟的方法):

export const getNextId = (): Promise<number> => {
   return new Promise<number>((resolve, reject) => {
      // not the actual call, but akin to it
      getDB().then((db: LowdbAsync<Schema>) => {
        resolve(db.get('count').value()) as number
    }
}

然后在不同的文件中,我使用它来设置ID(这用于某些I / O)。

import { getNextId } from '../../db'

export interface Job {
 id: number
}

export class Job implements Job {
 constructor(public id: number) { }
}

export const getNewJob = (): Promise<Job> => {
  return new Promise<Job>((resolve, reject) => {
   getNextId().then((id: number) => {
     resolve(new Job(id))
   }
  }
 }

就像那样丑陋,这就是所需要的。

因此,在我的测试文件中,我有一行代码可以创建一个新的Job。我可以通过修改构造函数来思考如何解决这个问题,但我宁愿这样做惯用

到目前为止,这是最接近的我已经得到了它的工作。这只是防止它在运行时爆炸(测试,即),但它实际上并没有调用我的手动模拟函数。

看哪:

const db = jest.createMockFromModule('../../db')
  // this is ugly but i'm using TS on strict
  db['getNextId'] = (): Promise<number> => {
    return new Promise<number>((resolve, reject) => {
      resolve(0)
    }
 }

 import { someUtilMethod } from '../../app/util'
 import { Job, getNewJob } from '../../app/job'

 describe('foo', () => {
   getNewJob().then((job: Job) => {
     let testVal: string = someUtilMethod(job)
     // then assert some value here
   }
 }    

虽然开始模仿本地模块似乎确实让它运行(没有getNextId未定义的问题)但它实际上从未调用我的手动模拟函数。我尝试了一些方法,这是至少让测试运行的唯一方法...但是{永远不会设置id值并且日志/调试验证手动模拟功能从未被击中。

我可以很容易地做一些愚蠢的事情,但是从我读过的所有应该工作。我甚至尝试了基本的非Promise基本调用(这显然不是我的问题),并且调用方法来获取辅助方法之外的ID(例如在测试中)都无济于事。在jest加载模块的过程中,我遗漏了一些东西。

1 个答案:

答案 0 :(得分:0)

Havent尝试使用jest.createMockFromModule。我喜欢使用jest.spyOn参见jest docs' example,它可以模拟模块的特定功能,并且可以在每个测试中完成(即使用mockRestore()将功能恢复为正常)。

顺便说一句,我还在it内添加了describe以使其正常运行,并在await中添加了要解决的测试。

测试:

import * as db from '../src/db';
import { Job, getNewJob } from '../src/stackoverflow2';

//  import { someUtilMethod } from '../../app/util'
const someUtilMethod = (job: Job) => JSON.stringify(job);

describe('foo', () => {
    it('bar', async () => {
        const getNextIdSpy = jest.spyOn(db, 'getNextId');

        getNextIdSpy.mockResolvedValue(5);

        await getNewJob().then((job: Job) => {
            let testVal: string = someUtilMethod(job);
            // then assert some value here
            expect(testVal).toBe('{"id":5}');
        });

        getNextIdSpy.mockRestore();
    });
});