【发布时间】: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