MockK无法区分命令子类类型,如何按类型返回模拟结果?
我之前也碰到过这个坑,本质是JVM泛型类型擦除搞的鬼,MockK没法靠泛型父类的类型参数精准区分这两个命令。给你几个靠谱的解决办法:
方法1:用match匹配器检查实例类型
直接判断传入的命令到底是哪个子类,这种方式最直观,不会出错:
@Test fun `getActiveIndices should make correct calls`() { val aliases = listOf(/* 你的AliasModel列表 */) val indices = listOf(/* 你的IndexModel列表 */) // 精准匹配GetAllAliasesCommand类型的实例 every { elasticsearchCommandExecutor.execute(match { it is GetAllAliasesCommand }) } returns aliases // 精准匹配GetAllIndicesCommand类型的实例 every { elasticsearchCommandExecutor.execute(match { it is GetAllIndicesCommand }) } returns indices val result = indexService.getActiveIndices(ElasticsearchCluster.SOME_CLUSTER) verify(exactly = 1) { elasticsearchCommandExecutor.execute(any<GetAllAliasesCommand>()) } verify(exactly = 1) { elasticsearchCommandExecutor.execute(any<GetAllIndicesCommand>()) } assert(result == /* 预期的IndexModel列表 */) }
方法2:用ofType匹配器(更简洁)
MockK专门提供了ofType<T>()匹配器,用来匹配指定类型的实例,写法更清爽:
@Test fun `getActiveIndices should make correct calls`() { val aliases = listOf(/* 你的AliasModel列表 */) val indices = listOf(/* 你的IndexModel列表 */) every { elasticsearchCommandExecutor.execute(ofType<GetAllAliasesCommand>()) } returns aliases every { elasticsearchCommandExecutor.execute(ofType<GetAllIndicesCommand>()) } returns indices val result = indexService.getActiveIndices(ElasticsearchCluster.SOME_CLUSTER) verify(exactly = 1) { elasticsearchCommandExecutor.execute(ofType<GetAllAliasesCommand>()) } verify(exactly = 1) { elasticsearchCommandExecutor.execute(ofType<GetAllIndicesCommand>()) } assert(result == /* 预期的IndexModel列表 */) }
方法3:直接用具体命令实例匹配(最稳妥)
如果你的命令类可以直接实例化,干脆用具体的实例来匹配,绝对不会混淆:
@Test fun `getActiveIndices should make correct calls`() { val aliases = listOf(/* 你的AliasModel列表 */) val indices = listOf(/* 你的IndexModel列表 */) val aliasesCommand = GetAllAliasesCommand(ElasticsearchCluster.SOME_CLUSTER) val indicesCommand = GetAllIndicesCommand(ElasticsearchCluster.SOME_CLUSTER) every { elasticsearchCommandExecutor.execute(aliasesCommand) } returns aliases every { elasticsearchCommandExecutor.execute(indicesCommand) } returns indices val result = indexService.getActiveIndices(ElasticsearchCluster.SOME_CLUSTER) verify(exactly = 1) { elasticsearchCommandExecutor.execute(aliasesCommand) } verify(exactly = 1) { elasticsearchCommandExecutor.execute(indicesCommand) } assert(result == /* 预期的IndexModel列表 */) }
为啥原来的写法会失效?
核心原因是JVM泛型类型擦除:虽然GetAllAliasesCommand和GetAllIndicesCommand是ElasticsearchCommand<T>的不同子类,但运行时泛型参数会被擦除,MockK没法通过any<CommandType>()精准区分这两个命令的泛型父类类型,导致最后一条every规则覆盖了前面的。
用上面的方法明确匹配实例的具体类型,就能绕开这个问题啦。
内容的提问来源于stack exchange,提问作者Enes Keles
相关产品推荐
相关产品推荐

