开玩笑:我的独立模块功能依赖于在同一模块上找到的功能。 mock 之后,还是依赖原来的实现

JEST: My Isolated module function depends on a function found on the same module. After mocking, it still relies on the original implementation

我有

abc.js

const a = (a)=>{
    return (b(a) + 1)
}

const b = (num)=>{
    return(num + 1)
}

module.exports = {
    a,
    b
}

当我对函数 a 进行测试时,我想要函数 b 的模拟实现。但是函数a,在模拟之后,仍然使用原来的实现而不是我的模拟。

我的测试看起来像

abs.test.js

const { a } = require('./abc')

describe('/abc functions',()=>{

    beforeEach(()=>{
        jest.mock('./abc',()=>(
       b = jest.fn.mockReturnValue(5)
     ))
    })

    afterEach(()=>{
        jest.clearAllMocks()
    })

    it('uses the b() mock',()=>{



        const aResult = a(1)
        expect(aResult).toBe(6)
    })

})

但我得到的结果是 2 或任何原始实现。 我只是想让我的函数 a 使用我的模拟,但它从来没有。它总是回到原来的实现。

我尝试 jest.isolate() 来隔离即时测试功能。 我尝试了不同的模拟方式,例如 jest.fn()、jest.spyOn,以及关于 jest.requireActual(moduleName)

的方法

我试过 b = jest.fn().mockImplementation(()=>{})

我很困惑为什么函数 a,即使在隔离之后,仍然依赖于函数 b 的原始实现...

提前致谢!

解决问题的不同方法。 其中之一是通过将这些功能划分为自己的模块来进一步“模块化”这些功能。 有关此线程的更多信息: github.com/facebook/jest/issues/936#issuecomment-545080082

您必须记住词法作用域的规则以及它与闭包概念的关系。简短的回答是你的测试不工作的原因是因为在你的模块 abc.js 中你的函数 a() 在它的主体中调用了在同一个模块中声明的函数 b() .定义函数的环境而不是调用它的环境就是所谓的词法范围。这种函数体的组合使用了定义它的绑定以及在那些现有 bindings/environment 的上下文中调用该函数,这就是所谓的闭包。因此,如果您模拟一个函数 b() 并尝试使用该模拟来更改 a() 的 return 值并不重要,a() 将始终使用原始函数 b() 因为这是词法作用域规则 dictate