代码之家  ›  专栏  ›  技术社区  ›  Andrzej Sawoniewicz

使用Mockk模拟静态java方法

  •  46
  • Andrzej Sawoniewicz  · 技术社区  · 6 年前

    我们目前正在使用java和kotlin项目,慢慢地将整个代码迁移到后者。

    是否可以模拟静态方法,如 Uri.parse() 使用Mockk?

    示例代码是什么样子的?

    5 回复  |  直到 6 年前
        1
  •  86
  •   LeoColman    5 年前

    除了oleksiyp回答:

    mockk 1.8.1之后:

    Mockk版本1.8.1不推荐使用以下解决方案。在该版本之后,您应该执行以下操作:

    @Before
    fun mockAllUriInteractions() {
        mockkStatic(Uri::class)
        every { Uri.parse("http://test/path") } returns Uri("http", "test", "path")
    }
    

    mockkStatic 每次调用时都会被清除,因此您无需再对其解除锁定


    已弃用:

    如果您需要模拟的行为始终存在,而不仅仅是在单个测试用例中,那么您可以使用 @Before @After :

    @Before
    fun mockAllUriInteractions() {
        staticMockk<Uri>().mock()
        every { Uri.parse("http://test/path") } returns Uri("http", "test", "path")    //This line can also be in any @Test case
    }
    
    @After
    fun unmockAllUriInteractions() {
        staticMockk<Uri>().unmock()
    }
    

    这样,如果希望更多的类使用Uri类,可以在一个地方对其进行模拟,而不是用 .use 处处

        2
  •  18
  •   oleksiyp    6 年前

    MockK允许模拟静态Java方法。它的主要目的是模拟Kotlin扩展函数,因此它没有PowerMock强大,但即使对于Java静态方法,它也能完成这项工作。

    语法如下:

    staticMockk<Uri>().use {
        every { Uri.parse("http://test/path") } returns Uri("http", "test", "path")
    
        assertEquals(Uri("http", "test", "path"), Uri.parse("http://test/path"))
    
        verify { Uri.parse("http://test/path") }  
    }
    

    更多详细信息请参见: http://mockk.io/#extension-functions

        3
  •  14
  •   Tomas Rohovsky    3 年前

    当心

    如果你打电话 mockkSatic() 没有障碍,别忘了打电话 unmockkStatic() 调用模拟方法之后。该方法不会自动解除锁定,即使在不调用 mockkStatic() ,但使用静态方法。

    另一个选项是在块内执行模拟方法,然后它将自动解除锁定:

    mockkStatic(Uri::class) {
        every { Uri.parse("http://test/path") } returns Uri("http", "test", "path")
        val uri = Uri.parse("http://test/path")
    }
    
    
        4
  •  11
  •   Danilo Lemes    4 年前

    除公认答案外:

    无法创建 Uri 这样,您也必须模拟Uri实例。类似于:

    private val mockUri = mockk<Uri>()
    
    @Before
    fun mockAllUriInteractions() {
        mockkStatic(Uri::class)
        every { Uri.parse("http://test/path") } returns mockUri
        // or just every { Uri.parse("http://test/path") } returns mockk<Uri>()
    }
    
        5
  •  1
  •   neronovs    2 年前

    如果我们要模拟静态,例如: mockkStatic(Klass::类)

    然后我们一定要把它拆下来,比如: unckkstatic(Klass::类)

    我建议在添加了@After的方法中取消对其的锁定。

    一个完整的例子是:

    class SomeTest {
      private late var viewMode: SomeViewModel
    
      @Before
      fun setUp() {
        viewMode = SomeViewModel()
        mockkStatic(OurClassWithStaticMethods::class)       
      }
    
      @After
      fun tearDown() {
        unmockkStatic(OurClassWithStaticMethods::class)
      }
    
      @Test
      fun `Check that static method get() in the class OurClassWithStaticMethods was called`() {
        //Given
        every { OurClassWithStaticMethods.get<Any>(any()) } returns "dummyString"
    
        //When
        viewModel.doSomethingWhereStaticMethodIsCalled()
    
        //Then
        verify(exactly = 1) { 
           OurClassWithStaticMethods.get<Any>(any()) 
        }
      }
    }
    

    此示例使用mocking库编写” Mockk “v.1.12.0