【问题标题】:Kotlin - Mockito cannot mock/spy (Spring REST API)Kotlin - Mockito 无法模拟/监视(Spring REST API)
【发布时间】:2016-09-28 10:09:55
【问题描述】:

由于 Kotlin 中的所有类默认为 final,而 Mockito 无法监视最终类:

Cannot mock/spy class bye.persistence.jdbcTrial
Mockito cannot mock/spy following:
  - final classes
  - anonymous classes
  - primitive types

还有this guide (7 月 6 日,Danny Preussler)说需要一个框架来解决这个问题。

现在我想知道,是否可以测试 REST API(使用 Spring MockMvc)。下面是我的测试代码:

package byeTest.persistenceTest
import bye.domain.User
import bye.persistence.jdbcTrial
import bye.spring.GreetingController
import byeTest.persistenceTest.RestAPITest.RootConfig
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.BDDMockito.given
import org.mockito.Mockito
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.MediaType
import org.springframework.test.context.ContextConfiguration
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner
import org.springframework.test.context.web.WebAppConfiguration
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.content
import org.springframework.test.web.servlet.setup.MockMvcBuilders
import org.springframework.web.context.WebApplicationContext

@RunWith(SpringJUnit4ClassRunner::class)
@ContextConfiguration(classes = arrayOf(RootConfig::class))
@WebAppConfiguration
open class RestAPITest {
    var mockMvc: MockMvc? = null;

    @Autowired
    var wac : WebApplicationContext? = null;

    @Autowired
    var jdbcTrial : jdbcTrial? = null

    @Autowired
    var todoServiceMock : GreetingController? = null;

    @Before
    open fun setup(){
        mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build()
        given(this.jdbcTrial?.getUserById(2)).willReturn(User(2,"uname","typ"));

    }



    @Test
    open public fun find_2(){
        mockMvc!!.perform(get("/user/2").accept(MediaType.APPLICATION_JSON))

            .andExpect(content().string("{\"id\":2,\"username\":\"uname\",\"usertype\":\"typ\"}"))


    }

    @Configuration
    open class RootConfig{
        @Bean
        open fun jdbcTrial():jdbcTrial{
            return Mockito.mock(jdbcTrial::class.java)
        }
    }
}

我将所有使用的函数和类设置为open,因为根据kotlin docs,这与final 完全相反。但是使用这个(到处)仍然会抛出上面提到的异常。

import bye.domain.Comment
import bye.domain.Event
import bye.domain.Participant
import bye.domain.User
import java.sql.Connection
import java.sql.DriverManager
import java.sql.ResultSet
import java.sql.Statement
import java.util.ArrayList
import javax.sql.DataSource

open class jdbcTrial() {
    open var url: String = "jdbc:postgresql://rosdel.quintor.local:5432/quintorevents"
    //val props: Properties = Properties();

    open var DB_DRIVER = "org.postgresql.Driver";
    open var dataSource:String? = "b";

    constructor(s : String):this(){
        this.dataSource = s
    }

    open fun getFoo():String{
        var query : String = "select val_col from foo_tbl where key_col = 'foo';"
        var rs:ResultSet = this.getConnection().createStatement().executeQuery(query)
        var result:String = "wrong";
        while(rs.next()){
            result= rs.getString("val_col")
        }
        return result;
    }

    open fun getBaz():String{
        return "qux"
    }

    // /events
    open fun getAll(): List<Event> {
        return getMultipleEvents("select * from quintor_event;")
    }

    // /events/search
    open fun searchEvents(search: String): List<Event> {
        var query = "select * from quintor_event where title LIKE '%" + search + "%';"
        return getMultipleEvents(query)
    }

    // used for getting the comments
    open fun getUserById(id: Int): User {
        var query = "select * from quintor_user where id = ${id};";
        return getSingleUser(query)
    }
    ........

【问题讨论】:

  • 请注意jdbcTrial 类需要标记open 才能模拟它。由于您没有包含此类,因此我们无法确定问题所在。
  • 我添加了一些类,这是一个相当大的类atm,但你可以得出结论,其他所有功能都设置相同
  • 如果我复制 jdbcTrial 类并删除无法编译的方法,我完全可以使用 Mockito.mock(jdbcTrial::class.java) 模拟它。
  • 我得到Cannot mock/spy class bye.persistence.jdbcTrial Mockito cannot mock/spy following: - final classes - anonymous classes - primitive types at byeTest.persistenceTest.RestAPITest$RootConfig.jdbcTrial(RestAPITest.kt:60)
  • 我认为你应该重新考虑你的测试策略。与其嘲笑jdbcTrial 类(并做可怕的事情将其标记为open),不如让您的测试正常使用它。编写一个集成测试,用所需的User 数据填充数据库。我已经写了数百个这样的测试;这是一种比孤立的单元测试更好的方法,我这样说是作为开发一个 确实 模拟 final 类的 Java 模拟库的人。

标签: spring unit-testing testing mocking kotlin


【解决方案1】:

关于 kotlin 中的模拟最终类 - 您可以使用 mockito kotlin 库。它可以在 github 上找到。在此链接https://hadihariri.com/2016/10/04/Mocking-Kotlin-With-Mockito/ 中,您可以了解如何操作。我每天都在使用它,我也使用 spring 的 mockmvc 并且效果很好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多