kotlin:模拟注入的单元测试(mockK)

Posted

技术标签:

【中文标题】kotlin:模拟注入的单元测试(mockK)【英文标题】:kotlin : unit test with mock injection (mockK) 【发布时间】:2019-12-02 05:23:36 【问题描述】:

我按照许多博客的分步说明使用 MockK 实现模拟:

class SWServiceImplTest 

    @MockK
    lateinit var externalApi: ExternalApiService

    @InjectMockKs
    lateinit var SWService: SWServiceImpl

    @Before
    fun setUp() = MockKAnnotations.init(this)

    @Test
    fun SWCharacterReturnsCorrectValues() 

        every  externalApi.get<Characters>(Utils.SW_API)  returns mockCharacters()

        val result = SWService.swCharacter!!
        assertEquals("blue", result.first().color?.toLowerCase())
        assertEquals(result.size, 3)
    


我想将externalApi 注入我的SWService 服务并模拟注入对象(externalApi)的get 方法,但似乎忽略了模拟。

日志:

15:09:54.497 [main] DEBUG io.mockk.impl.instantiation.AbstractMockFactory - Creating mockk for <error "java.lang.NoClassDefFoundError: kotlin/coroutines/intrinsics/IntrinsicsKt"> name=externalApi#1
15:09:56.820 [main] DEBUG org.springframework.web.client.RestTemplate - HTTP GET https://xxx.xxx/
15:09:57.038 [main] DEBUG org.springframework.web.client.RestTemplate - Accept=[application/json, application/*+json]

org.springframework.web.client.RestClientException: No HttpMessageConverter for java.lang.Object and content type ""

在我的SWService 文件中,externalApi 在伴随对象中被初始化:

    companion object
        val api = ExternalApiService()
    

我的实现有问题吗? 谢谢

【问题讨论】:

你是如何在SWService 类中初始化externalApi 的?你能把那个代码也贴一下吗? 感谢@SuryavelTR 的评论。我更新了我的消息:它在我的类中的伴随对象中初始化 删除了一条评论。错过了关于 InjectMocks SWService 的要点。所以。您无法将 InjectMocks 注入伴随对象。我建议在构造函数中使用 api 类似的 lateinit var 作为字段或 val(相信这个也可以) 这能回答你的问题吗? How to mock a Kotlin singleton object? 【参考方案1】:

Kotlin 为 companion object 生成一个名为 Companion 的内部类。这个Companion 类将只有声明的字段的getter(在您的情况下为getApi())。但该字段由外部类SWService 维护。

所以 SWService 的等效 java 类看起来像。

public final class SWService 
   private static final ExternalApiService api = new ExternalApiService();

   public static final class Companion() 
       public final ExternalApiService getApi() 
          return SWService.api;
       
   

现在您要模拟 apistatic 字段。这可以使用powermockito 来完成。

添加这个依赖,

testImplementation "org.powermock:powermock-api-mockito2:2.0.0-beta.5"

在你的测试中,

public final class SWServiceTest 

   @MockK
   lateinit var api: ExternalApiService

   var service = SWService()

    @Before
    fun setUp() 
        MockKAnnotations.init(this)
        Whitebox.setInternalState(SWService::class.java,"api", api);
    

希望对你有帮助。

【讨论】:

感谢您的回复。我尝试使用powermock 实现,但我仍然遇到同样的错误...(为

以上是关于kotlin:模拟注入的单元测试(mockK)的主要内容,如果未能解决你的问题,请参考以下文章

使用 Kotlin 数据类的 Json 解析器正确返回 json 数据,但是为啥解析器(MockK)的单元测试会失败?

安卓Kotlin单元测试/ Collection, ArrayList依赖的解耦/ MockK

单元测试--mockk

使用多平台模拟 kotlin 中的常见测试

Kotlin Spring Boot 单元测试 - 添加 @TestExecutionListeners 不会注入依赖项

如何使用 SpringBoot2、JUnit5 和 Kotlin 将配置属性注入单元测试