Reactjs Kotlin JS中的单元测试
我有一个使用React的Kotlin JavaScript的简单项目。我添加了单元测试,但当我运行它们时,它们似乎调用了生产代码的主要方法,并且在试图达到不一致的DOM结构时,初始化失败。尽管被测试的类没有以任何方式引用React或DOM 从Intelij IDEA或通过Reactjs Kotlin JS中的单元测试,reactjs,unit-testing,kotlin-js,Reactjs,Unit Testing,Kotlin Js,我有一个使用React的Kotlin JavaScript的简单项目。我添加了单元测试,但当我运行它们时,它们似乎调用了生产代码的主要方法,并且在试图达到不一致的DOM结构时,初始化失败。尽管被测试的类没有以任何方式引用React或DOM 从Intelij IDEA或通过gradlew build运行时,错误看起来是相同的(为了清楚起见,我已将项目的完整路径替换为/APP/): ./settings.gradle.kts plugins { id("org.jetbrains.kotli
gradlew build
运行时,错误看起来是相同的(为了清楚起见,我已将项目的完整路径替换为/APP/):
./settings.gradle.kts
plugins {
id("org.jetbrains.kotlin.js") version "1.3.70-eap-184"
}
group = "org.example"
version = "1.0-SNAPSHOT"
repositories {
maven { setUrl("https://dl.bintray.com/kotlin/kotlin-eap") }
maven("https://kotlin.bintray.com/kotlin-js-wrappers/")
mavenCentral()
jcenter()
}
dependencies {
implementation(kotlin("stdlib-js"))
implementation("org.jetbrains:kotlin-react:16.13.0-pre.94-kotlin-1.3.70")
implementation("org.jetbrains:kotlin-react-dom:16.13.0-pre.94-kotlin-1.3.70")
implementation(npm("react", "16.13.1"))
implementation(npm("react-dom", "16.13.1"))
testImplementation(kotlin("test-js"))
}
kotlin.target.browser {
}
pluginManagement {
repositories {
maven { setUrl("https://dl.bintray.com/kotlin/kotlin-eap") }
mavenCentral()
maven { setUrl("https://plugins.gradle.org/m2/") }
}
}
rootProject.name = "example"
./src/main/resources/index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<div id="root"></div>
<script src="example.js"></script>
</body>
</html>
./src/test/kotlin/ExampleTest.kt
import kotlin.test.*
class ExampleTest {
@Test
fun foo() {
assertEquals(DummyClass().foo(), "foo")
}
}
如果我根本不引用生产代码(从测试中删除DummyClass().foo()
),或者main方法不调用render(document.getElementById(“root”))
,则不会发生错误
PS:如果有关系的话,我在Windows上运行代码,这不是正确的答案,但会立即解除您的阻止
答案指出,
测试环境没有为DOM提供应用程序id
我们的测试框架也是如此——它没有提供id为“root”的元素。
这使我相信测试框架没有使用main/resources/index.html
。异常跟踪确认-注意它是如何从\uuuuu webpack\uu require\uuuuu
理想的解决方案是让karma或webpack为我们的代码提供正确的index.html;但我不知道如何做到这一点
同时,你可以
- 将
作为index.html的一部分删除
- 让您的kotlin代码生成它,如下所示: ./src/main/kotlin/main.kt
import react.dom.*
import kotlin.browser.document
fun main(args: Array<String>) {
render(document.getElementById("root")) {
}
}
fun main(args:Array){
document.body!!.insertAdjacentHTML(“afterbegin”,“afterbegin”)
呈现(document.getElementById(“根”)){
}
}
希望这有帮助我也有同样的问题,我已经解决了。多亏了@Yogesh Nachnani的变通方法,我才明白遗漏了什么。事实上,并没有包括所有的资源文件。因此,首先我使用fs extra(将文件从资源复制到本地目录)创建了一个新的解决方案,然后在探索Karma时,我发现最干净的解决方案是使用代理将请求重定向到资源。因此,我在karma.config.js中使用了以下代码:
const path = require('path');
const resourcesSourcePath = path.resolve(__dirname, '../../../../build/processedResources/js/main');
const setupFile = path.resolve(__dirname, '../../../../src/test/setup.js');
config.files.unshift(setupFile);
config.proxies = {
"/strings/": "absolute" + resourcesSourcePath + "/strings/",
"/css/": "absolute" + resourcesSourcePath + "/css/",
"/images/": "absolute" + resourcesSourcePath + "/images/"
}
这样,如果你有很多资源,你就不必等待内容的拷贝了。然而,我没有找到在index.html上启动karma的方法,但由于我现在可以访问所有资源,我只是使用了@Yogesh Nachnani提出的解决方法,因为html文件通常对测试没有太大影响(至少对我来说)。因此,我添加了一个setup.js文件,该文件仅包含:
document.body.insertAdjacentHTML('afterbegin', "<div id='root'></div>");
document.body.insertAdjacentHTML('afterbegin',“”);
当您使用React的render(document.getElementById(“root”){}时,它可以防止出现呈现目标错误。谢谢。这是一个很好的解决方法。:)我会等待一个非变通解决方案,但如果它在赏金到期之前没有发生,你就会得到它谢谢你的解决办法。然而,sommeone找到了这个问题的解决方案吗?因为(至少对我来说)资源中的任何文件都不能使用,例如,它阻止我基于翻译文件进行测试。
fun main(args: Array<String>) {
document.body!!.insertAdjacentHTML("afterbegin", "<div id='root'></div>" )
render(document.getElementById("root")) {
}
}
const path = require('path');
const resourcesSourcePath = path.resolve(__dirname, '../../../../build/processedResources/js/main');
const setupFile = path.resolve(__dirname, '../../../../src/test/setup.js');
config.files.unshift(setupFile);
config.proxies = {
"/strings/": "absolute" + resourcesSourcePath + "/strings/",
"/css/": "absolute" + resourcesSourcePath + "/css/",
"/images/": "absolute" + resourcesSourcePath + "/images/"
}
document.body.insertAdjacentHTML('afterbegin', "<div id='root'></div>");