在MockK中模拟gradle项目不会调用存根方法

c6ubokkw  于 2023-11-18  发布在  其他
关注(0)|答案(1)|浏览(143)

我正在使用JUnit和MockK在Kotlin中编写一个单元测试来测试我的自定义Gradle任务。

open class CopySourceTask @Inject constructor(
    private val config: MyCustomExtension
) : DefaultTask() {

    @TaskAction
    override fun run() {
        if (!config.enableCopyConfig) {
            return
        }

        val sourceSetContainer =
            project.extensions.getByType(SourceSetContainer::class.java)

        project.copy {
            // Copy project source
            it.from(sourceSetContainer.getByName(SourceSet.MAIN_SOURCE_SET_NAME))
            it.into("${project.buildDir}/private/src")
        }
    }
}

字符串
下面是我的单元测试:

@ExtendWith(MockKExtension::class)
class CopySourceTaskTest {
    @MockK
    lateinit var customExtension: MyCustomExtension

    @MockK
    lateinit var dependencyEnabled: Property<Boolean>

    @MockK
    lateinit var sourceSetContainer: SourceSetContainer

    @BeforeEach
    fun setup() {
        every { customExtension.enableCopyConfig } returns dependencyEnabled
    }

    @Test
    fun testCopy() {
        val project = spyk(ProjectBuilder.builder().build())
        every { dependencyEnabled.get() } returns true
        every { project.extensions.getByType(SourceSetContainer::class.java) } returns sourceSetContainer
        val gradleTask = project.tasks.register(
            "CopySourceTask",
            CopySourceTask::class.java,
            customExtension
        )
       
        gradleTask.get().run()

       // Verify statements here
    }
}


单元测试由于以下错误而出错:org.gradle.api.UnknownDomainObjectException: Extension of type ‘SourceSetContainer’ does not exist. Currently registered extension types: [ExtraPropertiesExtension]
看起来every { project.extensions.getByType(…)语句没有被接受,它试图从项目中加载SourceSetContainer,而不是mocked语句。请让我知道我错过了什么。

mzillmmw

mzillmmw1#

声明:未经验证的代码。此代码是为了传达的想法,而不是复制粘贴盲目。
因为你的Project是一个实际的示例,而不是一个mock,所以对getByType的调用不能被mock掉。你需要监视extensions对象:

val extensionsSpy = spyk(project.extensions)
project.extensions = extensionsSpy

字符串
如果你能做到这一点,它将工作。如果你不能取代的扩展示例,你需要'闯入'与乌鸦酒吧的方法

val field = project::class.declaredFields.filter { it.name == "extensions" }.firstOrNull()!!
field.isAccessible = true
field.set(project, extensionsSpy)


请注意,如果你不替换项目示例中的扩展,mocking框架将永远不会命中项目对其自身属性的内部调用。对自己方法的调用也是如此。所以你只能捕获对象之间边界上的调用。

相关问题