Jest引用本地文件触发包链接错误问题求助
问题:React Native SDK单元测试中出现包未链接错误
项目结构
project │ └───src │ └───__tests__ │ │ │ manager.test.txt │ │ │ └───dictation │ │ manager.ts │ │ ... │ └───src │ └───exampleFileStream.ts │ └───lib │ │ ... └───package.json └───sdk.podspec ...
其中exampleFileStream.ts是依赖Native Modules的音频文件流类,被manager.ts引用。
package.json核心配置
{ "name": "sdk-test-project", "version": "0.1.3", "main": "src/index.tsx", "module": "lib/module/index", "types": "lib/typescript/index.d.ts", "react-native": "src/index", "source": "src/index", "devDependencies": { "@types/jest": "^28.1.2", "jest": "^28.1.1", "jest-websocket-mock": "^2.4.0", "react": "17.0.2", "react-native": "0.68.2", "react-native-builder-bob": "^0.18.3", "typescript": "^4.5.2" }, "peerDependencies": { "react": "*", "react-native": "*" }, "jest": { "preset": "react-native", "modulePathIgnorePatterns": [ "<rootDir>/example/node_modules", "<rootDir>/lib/" ], "modulePaths": ["<rootDir>/app/"] }, "react-native-builder-bob": { "source": "src", "output": "lib", "targets": [ "commonjs", "module", [ "typescript", { "project": "tsconfig.build.json" } ] ] } }
测试代码
import WS from "jest-websocket-mock"; import { Manager } from '../../src/dictation/manager'; test('When onApiMessage enabled, only the callback is called', async () => { const server = new WS("ws://localhost:1234"); const dm = Manager.method(""); ... });
运行Jest时的错误信息
The package 'sdk-test-project' doesn't seem to be linked. Make sure: - You have run 'pod install' - You rebuilt the app after installing the package - You are not using Expo managed workflow 15 | { 16 | get() { > 17 | throw new Error(LINKING_ERROR); | ^ 18 | }, 19 | } 20 | ); at Object.get (src/dictation/core/exampleFileStream:17:17) at new addListener (node_modules/react-native/Libraries/EventEmitter/NativeEventEmitter.js:53:45) at new ExampleFileStream (src/dictation/core/exampleFileStream:37:26) at new Manager (src/dictation/manager.ts:116:32) at Function.fromCustomUrl (src/dictation/manager.ts:104:12) at fromCustomUrl (src/__tests__/manager.test.tsx:13:33) at tryCatch (node_modules/@babel/runtime/helpers/regeneratorRuntime.js:86:17) at Generator._invoke (node_modules/@babel/runtime/helpers/regeneratorRuntime.js:66:24) at Generator.next (node_modules/@babel/runtime/helpers/regeneratorRuntime.js:117:21) at tryCatch (node_modules/@babel/runtime/helpers/regeneratorRuntime.js:86:17)
用户疑问
为什么引用同项目本地文件会出现包未链接的问题?这是否和native modules有关?
原因分析
这个错误确实和Native Modules直接相关。你的exampleFileStream.ts里应该通过NativeModules或NativeEventEmitter引用了原生模块,而Jest运行在Node.js环境中,没有加载React Native的原生环境,当代码尝试访问未被模拟的原生模块时,就会触发React Native默认的“未链接”错误提示(这个提示原本是给原生模块未正确link的情况,但测试环境里根本不存在原生模块,所以同样会触发)。
解决方法
你需要在Jest测试中模拟这些依赖的Native Modules,以下是几种可行方案:
方案1:在测试文件中直接模拟Native Modules
在测试文件顶部添加模拟逻辑,覆盖React Native的原生模块:
jest.mock('react-native', () => { const originalRN = jest.requireActual('react-native'); return { ...originalRN, NativeModules: { ...originalRN.NativeModules, // 替换成你实际依赖的原生模块名称和方法 YourNativeAudioModule: { addListener: jest.fn(), removeListeners: jest.fn(), startStreaming: jest.fn(), // 其他需要的方法/属性 }, }, NativeEventEmitter: jest.fn(() => ({ addListener: jest.fn(), removeListener: jest.fn(), })), }; });
方案2:全局模拟原生模块
- 在项目根目录创建
jest.setup.js文件,写入全局模拟逻辑:
jest.mock('react-native', () => { const originalRN = jest.requireActual('react-native'); return { ...originalRN, NativeModules: { ...originalRN.NativeModules, YourNativeAudioModule: { addListener: jest.fn(), removeListeners: jest.fn(), }, }, NativeEventEmitter: jest.fn(() => ({ addListener: jest.fn(), })), }; });
- 修改
package.json中的Jest配置,引入这个全局 setup 文件:
"jest": { "preset": "react-native", "modulePathIgnorePatterns": [ "<rootDir>/example/node_modules", "<rootDir>/lib/" ], "modulePaths": ["<rootDir>/app/"], "setupFilesAfterEnv": ["<rootDir>/jest.setup.js"] }
方案3:直接模拟exampleFileStream.ts类
如果不想处理底层原生模块的模拟,可以直接模拟整个exampleFileStream.ts:
jest.mock('../../src/dictation/src/exampleFileStream.ts', () => { return { default: jest.fn(() => ({ // 模拟你在测试中用到的类方法 start: jest.fn(), on: jest.fn(), // 其他需要的方法 })), }; });
总结
错误和本地文件引用无关,核心是Jest没有原生环境,任何依赖Native Modules的代码都必须被模拟才能正常运行。你看到的“未链接”提示是React Native在无法找到原生模块时的默认错误,本质是原生模块在测试环境中不存在。
内容的提问来源于stack exchange,提问作者Jc781
相关产品推荐
相关产品推荐

