Typescript 如何使用jest模拟返回函数的函数

Typescript 如何使用jest模拟返回函数的函数,typescript,unit-testing,jestjs,mocking,Typescript,Unit Testing,Jestjs,Mocking,我试图模拟返回另一个函数的函数。然而,我不知道如何使用笑话来完成这项工作。提前谢谢 应该成功返回 应该抛出一个错误 需要模拟的模块: const initGreeter = () =>{ return { sayHello: (name:string) =>{ console.log(`Hello: ${name}`) } } } export default initGreeter; 正在测试的模块: im

我试图模拟返回另一个函数的函数。然而,我不知道如何使用笑话来完成这项工作。提前谢谢

  • 应该成功返回
  • 应该抛出一个错误
  • 需要模拟的模块:

    
    const initGreeter = () =>{
        return {
            sayHello: (name:string) =>{
                console.log(`Hello: ${name}`)
            }
        }
    }
    export default initGreeter;
    
    正在测试的模块:

    import initGreeter from './greeter';
    
    export const greetSomeone = (name:string) =>{
        const greeter = initGreeter();
        greeter.sayHello(name)
    }
    
    测试:

    import initGreeter from '../../utils/greeter';
    import { greetSomeone } from '../../utils/greeterConsumer';
    
    describe('greeterConsumer', () => {
      afterEach(() => {
        jest.clearAllMocks();
      });
    
      it('greeter consumer should call SayHello on greeter', () => {
        //TODO:mock greeter here
        greetSomeone('sam');
        expect(greeter.sayHello.mock.call[0][0]).toBe('sam');
      });
    
      it('greeter consumer throws exception', () => {
        //TODO:mock greeter here so it throws exception
        expect(greetSomeone('sam')).toThrow(Error);
      });
    });
    
    
    请注意,更新1和2中的代码是@slideshowp2解决方案中代码的延续。

    更新2:看起来像是更改了下面的代码

    jest.mock('./greeter', () => {
      return jest.fn(() => mGreeter);
    });
    

    它起作用了

    还有其他方法可以使@slideshowp2中的代码按原样工作,例如在tsconfig中设置“esModuleInterop”:true。然而,我不完全理解为什么这两种情况都适用。我可能会检查在未来和更新这里

    更新1:从@slideshowp2实现解决方案后

    我在测试中发现了下面的错误

    src/测试失败/utils/greeterConsumer.test.ts ● 接待员消费者›接待员消费者应在接待员电话中呼叫SayHello

    TypeError: greeter_1.default is not a function
    
      2 | 
      3 | export const greetSomeone = (name:string) =>{
    > 4 |     const greeter = initGreeter();
        |                     ^
      5 |     greeter.sayHello(name)
      6 | }
    
      at Object.<anonymous>.exports.greetSomeone (src/utils/greeterConsumer.ts:4:21)
      at Object.<anonymous> (src/__tests__/utils/greeterConsumer.test.ts:18:5)
    
    TypeError:greeter_1.default不是函数
    2 | 
    3 |导出常量greetSomeone=(名称:string)=>{
    >4 | const greeter=initGreeter();
    |                     ^
    5 |迎宾员,您好(姓名)
    6 | }
    at Object..exports.greetSomeone(src/utils/greeterConsumer.ts:4:21)
    反对。(src/\uuuu测试/utils/greeterConsumer.test.ts:18:5)
    
    您可以使用来手动模拟
    。/../utils/greeter
    模块

    例如

    greeter.ts

    const initGreeter=()=>{
    返回{
    sayHello:(名称:string)=>{
    log(`Hello:${name}`);
    },
    };
    };
    导出默认初始迎宾器;
    
    greeterConsumer.ts

    import initGreeter from./greeter';
    导出常量greetSomeone=(名称:string)=>{
    常量greeter=initGreeter();
    迎宾员:您好(姓名);
    };
    
    greeterConsumer.test.ts

    import initGreeter from./greeter';
    从“./greeterConsumer”导入{greetSomeone};
    常数管理器={
    sayHello:jest.fn(),
    };
    嘲笑('./问候者',()=>{
    return jest.fn(()=>mGreeter);
    });
    描述('greeterConsumer',()=>{
    之后(()=>{
    开玩笑。clearAllMocks();
    });
    it('接线员消费者应在接线员上呼叫SayHello',()=>{
    问候某人(“山姆”);
    expect(initGreeter).toBeCalledTimes(1);
    期望(mGreeter.sayHello).toBeCalledWith('sam');
    });
    它('greeter consumer抛出异常',()=>{
    mGreeter.sayHello.mockImplementationOnce(()=>{
    抛出新错误('oops');
    });
    expect(()=>greetSomeone('sam')).tothrower('oops');
    expect(initGreeter).toBeCalledTimes(1);
    期望(mGreeter.sayHello).toBeCalledWith('sam');
    });
    });
    
    单元测试结果:

     PASS  examples/65281989/greeterConsumer.test.ts
      greeterConsumer
        ✓ greeter consumer should call SayHello on greeter (3 ms)
        ✓ greeter consumer throws exception (10 ms)
    
    --------------------|---------|----------|---------|---------|-------------------
    File                | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
    --------------------|---------|----------|---------|---------|-------------------
    All files           |     100 |      100 |     100 |     100 |                   
     greeterConsumer.ts |     100 |      100 |     100 |     100 |                   
    --------------------|---------|----------|---------|---------|-------------------
    Test Suites: 1 passed, 1 total
    Tests:       2 passed, 2 total
    Snapshots:   0 total
    Time:        4.473 s
    

    源代码:

    感谢@slideshowp2的详细回复。不幸的是,我从测试“greeter consumer应该调用greeter上的SayHello”中得到错误“TypeError:greeter_1.default不是函数”。请参阅op的更新部分的详细信息。在我这方面是否有一些用于搞笑的配置设置?看起来我能够让它正常工作。请参阅OP中的更新2。再次感谢@slideshowp2的详细回复。
     PASS  examples/65281989/greeterConsumer.test.ts
      greeterConsumer
        ✓ greeter consumer should call SayHello on greeter (3 ms)
        ✓ greeter consumer throws exception (10 ms)
    
    --------------------|---------|----------|---------|---------|-------------------
    File                | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
    --------------------|---------|----------|---------|---------|-------------------
    All files           |     100 |      100 |     100 |     100 |                   
     greeterConsumer.ts |     100 |      100 |     100 |     100 |                   
    --------------------|---------|----------|---------|---------|-------------------
    Test Suites: 1 passed, 1 total
    Tests:       2 passed, 2 total
    Snapshots:   0 total
    Time:        4.473 s