我有一个要测试的来自其他Observable的简单Observable管道。
const loginState$ = messageBusObservables.loginState$.pipe(
startWith({ isLoggedIn: false })
pluck('isLoggedIn'),
distinctUntilChanged()
)
messageBusObservables是可观察对象。其中loginState $是可观察的。
在测试中,我认为我可以轻松地像这样模拟'./messageBus'模块:(该模块的导入方式无关紧要,但首选导入)
import { of } from 'rxjs'
import './messageBus'
jest.mock('./messageBus', () => ({
loginState$: of({ isLoggedIn: true }),
}))
但是,Jest抛出了错误:
babel-plugin-jest-hoist:
jest.mock()
的模块工厂不允许引用任何范围外的变量。 无效的变量访问:of
我尝试过将其放入jest.fn()
中,我尝试将of({ isLoggedIn: true })
提取到变量中。但是我总是从玩笑中得到同样的错误。
那么我该如何使用Jest模拟输入到Observable的内容呢?我将使用.merge,.zip等其他可观察对象遇到相同的问题。
它必须是真实的可观察物,是我其他可观察物的输入。我只想使用of()
之类的值来模拟值,而不是模拟带有方法的对象,该方法使用.pipe方法等返回对象。(我不想模拟可观察)。我想通过在单元测试中设置的值将其传递给真实的可观察对象。
我还需要这些模拟是动态的。因此,来自1断言的模拟可能不同于下一个断言中的模拟。 (用beforeEach之类的东西清除它们)
编辑:
我还尝试使用babel-plugin-rewire来模拟此模块,在我模拟它的* .test.js文件中,它工作正常。但是在实际文件中,无论我将导出设置为使用rewire进行什么操作,它始终都将作为原始的Observable导入。
答案 0 :(得分:2)
您已经关闭。
您正在尝试通过passing a module factory as the second parameter to jest.mock
模拟该模块。这种方法的主要限制是模块工厂必须完全独立,并且“不允许引用任何范围外的变量”。
从模块工厂中的of
引用rxjs
(您已经发现)打破了该约束,并导致了您看到的错误。
幸运的是,还有其他模拟模块的方法。
从您的代码中可以看出,最简单的方法似乎是创建messageBus
模块的Manual Mock。
在与__mocks__
相同的目录中创建一个messageBus.js
文件夹,并在messageBus.js
文件夹中创建模拟对象(也称为__mocks__
)。
__mocks__/messageBus.js
看起来像这样:
import { of } from 'rxjs'
export default {
loginState$: of({ isLoggedIn: true })
}
然后通过致电tell Jest you want to use the manual mock within your test
jest.mock('messageBus');
位于测试文件的顶部。
That call is hoisted by Jest,并确保在测试过程中导入messageBus
的所有代码都将获得模拟模块。
答案 1 :(得分:1)
收到此消息的原因:
babel-plugin-jest-hoist:jest.mock()的模块工厂不允许引用任何范围外的变量。无效的变量访问:of
是因为jest自动将调用提升到jest.mock,以便它们在导入之前发生。
您有两种方法可以避免这种默认行为,简单的方法是使用未悬挂的jest.doMock:
jest.doMock('./messageBus', () => ({
loginState$: of({ isLoggedIn: true }),
}))
或者,您可以在传递给jest.mock的模拟工厂中引用的所有变量前面加上“ mock”:
const mockMessageBus = {
loginState$: of({ isLoggedIn: true }),
}
jest.doMock('./messageBus', () => mockMessageBus)
(请注意,当调用jest.mock时,您有责任确保工厂函数中引用的所有模拟变量都在范围内)