Javascript Jest模拟方法根据输入返回特定的结果 tl;博士

Javascript Jest模拟方法根据输入返回特定的结果 tl;博士,javascript,jestjs,Javascript,Jestjs,当输入为X时,我试图模拟fs.readdirSync() 因此,最初我模拟了该方法并添加了所需的输出 fs.readdirSync = jest.fn(); fs.readdirSync.mockReturnValue(['my data here']); 虽然现在它总是使用那个输出,但是我只想要一次,其他的应该是原来的方法, 因此,AFAIU可以模拟该方法,但仍可以使用原始方法的默认值 const originalReaddirSync = fs.readdirSync; fs.readd

当输入为
X
时,我试图模拟
fs.readdirSync()


因此,最初我模拟了该方法并添加了所需的输出

fs.readdirSync = jest.fn();
fs.readdirSync.mockReturnValue(['my data here']);
虽然现在它总是使用那个输出,但是我只想要一次,其他的应该是原来的方法, 因此,AFAIU可以模拟该方法,但仍可以使用原始方法的默认值

const originalReaddirSync = fs.readdirSync;
fs.readdirSync = jest.fn(path => originalReaddirSync(path));
fs.readdirSync.mockReturnValueOnce(['my data here']);
这几乎完成了预期的工作,但我要覆盖的调用是第二个调用

Q:如果
路径
X
返回
Y
,是否有一种说法?


我来自PHP背景,我正试图用mocky实现以下示例

$mockedObject->shouldReceive('method')
    ->once()
    ->with('this argument')
    ->andReturn(['my data here']);

您可以为每个测试用例模拟一次该值:

index.ts

import fs from 'fs';

function readdirSync(path) {
  return fs.readdirSync(path);
}

export { readdirSync };

import { readdirSync } from './';
import fs from 'fs';

fs.readdirSync = jest.fn();

describe('readdirSync', () => {
  it('t1', () => {
    (fs.readdirSync as jest.MockedFunction<any>).mockReturnValueOnce(['Y']);
    const actualValue = readdirSync('X');
    expect(actualValue).toEqual(['Y']);
    expect(fs.readdirSync).toBeCalledWith('X');
  });

  it('t2', () => {
    (fs.readdirSync as jest.MockedFunction<any>).mockReturnValueOnce(['Z']);
    const actualValue = readdirSync('T');
    expect(actualValue).toEqual(['Z']);
    expect(fs.readdirSync).toBeCalledWith('T');
  });
});

索引规范ts

import fs from 'fs';

function readdirSync(path) {
  return fs.readdirSync(path);
}

export { readdirSync };

import { readdirSync } from './';
import fs from 'fs';

fs.readdirSync = jest.fn();

describe('readdirSync', () => {
  it('t1', () => {
    (fs.readdirSync as jest.MockedFunction<any>).mockReturnValueOnce(['Y']);
    const actualValue = readdirSync('X');
    expect(actualValue).toEqual(['Y']);
    expect(fs.readdirSync).toBeCalledWith('X');
  });

  it('t2', () => {
    (fs.readdirSync as jest.MockedFunction<any>).mockReturnValueOnce(['Z']);
    const actualValue = readdirSync('T');
    expect(actualValue).toEqual(['Z']);
    expect(fs.readdirSync).toBeCalledWith('T');
  });
});

更新

您也可以使用
jest.fn().mockImplementation()

单元测试

  • 如果路径为X,则返回Y

  • 如果路径为T,则返回Z

  • 单元测试结果:

    PASS src/stackoverflow/46911799/index-2.spec.ts
    readdirSync
    ✓ t3(5毫秒)
    ✓ t4(1ms)
    测试套件:1个通过,共1个
    测试:2次通过,共2次
    快照:共0个
    时间:4.345秒
    
    哇,你真的深入地找到了这个老问题,非常感谢你的回答。。。不过,这是一种不同的工作方式,我们甚至可以说这是一种错误的工作方式,对于JS来说,在运行中模仿它要容易得多。这很管用,但不是我想要的。我会@mloureiro更新答案,这就是你要找的吗?我只是做了那个答案,无论如何,非常感谢,我会把它标记为正确的!❤️