【问题标题】:Jest spyOn to mock implementation only on second call and the third callJest spyOn 仅在第二次调用和第三次调用时模拟实现
【发布时间】:2020-08-10 12:14:12
【问题描述】:

我有一个函数,我只想在第二次调用和第三次调用时模拟,但在第一次调用时使用默认实现。我查看了 Jest 文档,并且有一个函数 mockImplementationOnce 可以用来模拟单个调用的实现。

有没有我可以使用的函数,它会在第一次调用时使用默认实现,并且只模拟第二次和第三次调用?

let functionCalls = 0;
const database = {
  fetchValues() {
    fetchValues();
    fetchValues();
  },
};
jest.spyOn(database, 'fetchValues')
.useDefaultImplementation() // <-- is there such a function?
.mockImplementationOnce(() => 42)
.mockImplementationOnce(() => 42)

【问题讨论】:

    标签: javascript node.js mocking jestjs


    【解决方案1】:

    您可以使用mockImplementation 方法来模拟默认实现。见mock-implementations

    例如

    const database = {
      fetchValues() {
        return 'real data';
      },
    };
    
    describe('61450440', () => {
      afterEach(() => {
        jest.restoreAllMocks();
      });
      it('should pass', () => {
        jest
          .spyOn(database, 'fetchValues')
          .mockImplementation(() => 'default')
          .mockImplementationOnce(() => 'first call')
          .mockImplementationOnce(() => 'second call');
    
        console.log(
          [database.fetchValues(), database.fetchValues(), database.fetchValues(), database.fetchValues()].join(','),
        );
      });
      it('should pass too', () => {
        jest
          .spyOn(database, 'fetchValues')
          .mockImplementation(() => 'real data')
          .mockImplementationOnce(() => 'real data')
          .mockImplementationOnce(() => 'first call')
          .mockImplementationOnce(() => 'second call');
    
        console.log(
          [database.fetchValues(), database.fetchValues(), database.fetchValues(), database.fetchValues()].join(','),
        );
      });
    
      it('should pass 3', () => {
        const fetchValuesSpy = jest.spyOn(database, 'fetchValues');
        console.log('call original fetchValues:', database.fetchValues());
        fetchValuesSpy.mockImplementationOnce(() => 'first call').mockImplementationOnce(() => 'second call');
        console.log('call mocked fetchValues:', database.fetchValues(), database.fetchValues());
        console.log('call original fetchValues again:', database.fetchValues());
      });
    });
    

    测试结果:

     PASS  stackoverflow/61450440/index.test.ts (13.748s)
      61450440
        ✓ should pass (20ms)
        ✓ should pass too (1ms)
        ✓ should pass 3 (12ms)
    
      console.log stackoverflow/61450440/index.test.ts:15
        first call,second call,default,default
    
      console.log stackoverflow/61450440/index.test.ts:27
        real data,first call,second call,real data
    
      console.log stackoverflow/61450440/index.test.ts:34
        call original fetchValues: real data
    
      console.log stackoverflow/61450440/index.test.ts:36
        call mocked fetchValues: first call second call
    
      console.log stackoverflow/61450440/index.test.ts:37
        call original fetchValues again: real data
    
    Test Suites: 1 passed, 1 total
    Tests:       3 passed, 3 total
    Snapshots:   0 total
    Time:        15.761s
    

    【讨论】:

    • 在你的例子中,我应该如何修改它,以便控制台日志输出“真实数据,第一次调用,第二次调用,真实数据”
    • @Stanley “真实数据”表示您调用原始fetchValues 并从数据库中返回真实数据。它可能会导致测试失去隔离。那是你真正想要的吗?
    • @Stanley 查看第三个测试用例。
    • 恐怕我无法根据您的第三次测试将它们分开,因为 fetchValues 就像一个调用自身的递归函数。我已经更新了问题以显示这种情况
    • @Stanley fetchValues 函数是什么?可以提供代码吗?
    猜你喜欢
    • 2012-07-31
    • 1970-01-01
    • 2018-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-03
    • 1970-01-01
    • 2011-10-26
    相关资源
    最近更新 更多