使用Scalatest测试Scala.js+Slinky React Native应用报错求助
问题描述
我正尝试用Slinky创建React Native应用,并用Scala.js版的Scalatest运行测试。build.sbt的依赖配置如下:
scalaVersion := "2.13.8" libraryDependencies += "me.shadaj" %%% "slinky-native" % "0.7.0" libraryDependencies += "me.shadaj" %%% "slinky-hot" % "0.7.0" libraryDependencies += "org.scalatest" %%% "scalatest" % "3.2.13" % "test"
编写基础测试后,执行sbt test命令时出现如下错误:
[info] Fast optimizing /Users/arindamray/IdeaProjects/temp/DanceApp/target/scala-2.13/app-test-fastopt /Users/arindamray/IdeaProjects/temp/DanceApp/node_modules/react-native/index.js:14 import typeof AccessibilityInfo from './Libraries/Components/AccessibilityInfo/AccessibilityInfo'; ^^^^^^ SyntaxError: Cannot use import statement outside a module at Object.compileFunction (node:vm:352:18) at wrapSafe (node:internal/modules/cjs/loader:1033:15) at Module._compile (node:internal/modules/cjs/loader:1069:27) at Object.Module._extensions..js (node:internal/modules/cjs/loader:1159:10) at Module.load (node:internal/modules/cjs/loader:981:32) at Function.Module._load (node:internal/modules/cjs/loader:822:12) at Module.require (node:internal/modules/cjs/loader:1005:19) at require (node:internal/modules/cjs/helpers:102:18) at Object.<anonymous> (/Users/arindamray/IdeaProjects/temp/DanceApp/target/scala-2.13/app-test-fastopt/main.js:3:27) at Module._compile (node:internal/modules/cjs/loader:1105:14) [error] org.scalajs.testing.common.RPCCore$ClosedException: org.scalajs.testing.adapter.JSEnvRPC$RunTerminatedException [error] at org.scalajs.testing.common.RPCCore.helpClose(RPCCore.scala:223) [error] at org.scalajs.testing.common.RPCCore.close(RPCCore.scala:215) [error] at org.scalajs.testing.adapter.JSEnvRPC.close(JSEnvRPC.scala:68) [error] at org.scalajs.testing.adapter.JSEnvRPC.$anonfun$new$1(JSEnvRPC.scala:59) [error] at org.scalajs.testing.adapter.JSEnvRPC.$anonfun$new$1$adapted(JSEnvRPC.scala:59) [error] at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:64) [error] at java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1426) [error] at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290) [error] at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020) [error] at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656) [error] at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594) [error] at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183) [error] Caused by: org.scalajs.testing.adapter.JSEnvRPC$RunTerminatedException [error] at org.scalajs.testing.adapter.JSEnvRPC.$anonfun$new$1(JSEnvRPC.scala:59) [error] at org.scalajs.testing.adapter.JSEnvRPC.$anonfun$new$1$adapted(JSEnvRPC.scala:59) [error] at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:64) [error] at java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1426) [error] at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290) [error] at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020) [error] at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656) [error] at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594) [error] at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183) [error] Caused by: org.scalajs.jsenv.ExternalJSRun$NonZeroExitException: exited with code 1 [error] at org.scalajs.jsenv.ExternalJSRun$$anon$1.run(ExternalJSRun.scala:195)
请问该如何修复此问题?若有调试线索也请不吝赐教。
修复方案
1. 配置Node.js以ES模块模式运行测试
Scala.js默认用CommonJS模式编译测试代码,但React Native依赖是ES模块格式,导致Node.js将其识别为非模块文件报错。需要修改编译配置并告知Node.js使用ES模块:
在build.sbt中添加:
// 全局设置ES模块编译 scalaJSLinkerConfig ~= { _.withModuleKind(ModuleKind.ESModule) } // 单独为测试环境设置ES模块编译 Test / scalaJSLinkerConfig ~= { _.withModuleKind(ModuleKind.ESModule) }
同时在项目根目录创建package.json,添加:
{ "type": "module" }
2. 改用JSDOM作为测试环境
React Native的API依赖原生移动环境,纯Node.js无法模拟。使用JSDOM可以提供浏览器环境的模拟,同时天然支持ES模块:
首先添加JSDOM依赖到测试范围:
libraryDependencies += "org.scala-js" %%% "scalajs-jsenv-jsdom-nodejs" % "1.13.0" % Test
然后在build.sbt中指定测试环境:
Test / jsEnv := new org.scalajs.jsenv.jsdomnodejs.JSDOMNodeJSEnv()
3. Mock React Native模块(适合单元测试)
如果仅测试Slinky组件的逻辑,不需要完整的React Native环境,可以mock掉相关组件:
创建测试用mock文件(如src/test/scala/mocks/ReactNativeMock.scala):
import slinky.core.ExternalComponent object ReactNativeMock { object View extends ExternalComponent { override val component = "div" } // 根据测试需求,mock Text、Image等其他React Native组件 }
在测试代码中使用这些mock组件替代原生的React Native组件,避免加载真实的React Native依赖。
调试线索
- 检查Node.js版本:确保使用v14及以上版本,该版本对ES模块支持更完善
- 查看编译输出:检查
target/scala-2.13/app-test-fastopt/main.js的模块格式,确认是否为ES模块 - 重置依赖:删除
node_modules和package-lock.json,重新执行npm install,确保React Native依赖安装完整
内容的提问来源于stack exchange,提问作者arinray
相关产品推荐
相关产品推荐

