【发布时间】:2021-03-21 22:27:27
【问题描述】:
所以我有一个用 kotlin 编写的非常基本的模型、dao 和控制器类。我正在使用 Ebean 连接服务和数据。我正在尝试为我的 DAO 类创建单元测试。据我了解,单元测试实际上不应调用 db 连接,即使我已经读到有些人已将我的堆栈与 DBUnit 结合起来进行此类测试。
但是,我选择了与 Mockito 不同的方法,并尝试按照 ebean 的说明进行操作,如下所述:https://ebean.io/docs/setup/testing 我能够创建模拟数据库对象并使用 getBeanId(null) 函数运行测试。但是当我尝试改变
when(dbmock.getBeanId(null)).thenReturn(someBeanId)
到
when(dbmock.find(PracticeSession::class.java).where(Expr.eq("id", 1)).findOne()!!).thenReturn(mockPracticeSession)
我收到此错误:
java.lang.NullPointerException: Cannot invoke "io.ebean.Query.where(io.ebean.Expression)" because the return value of "io.ebean.Database.find(java.lang.Class)" is null
所以有什么建议我应该如何继续这样做或我做错了什么?在我看来,dbmock 与真正的 DB 对象不同,因为只有一些函数在工作。 e. getBeanId 有效,但 find() 无效。我需要用什么来初始化它吗?我假设在 DAO 类中调用 DB.find() 时也会出现问题。
这是我的模型,
import io.ebean.Model
import io.ebean.annotation.NotNull
import org.flywaydb.core.internal.configuration.ConfigUtils.TABLE
import java.util.*
import javax.persistence.*
@Entity
class PracticeSession : Model() {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long = 0
var name: String? = null
@NotNull
var date: Date? = null
@NotNull
var duration = 0
@ManyToOne(optional = false)
var location: Location? = null
@ManyToOne(optional = false)
var climber: Climber? = null
}
道,
import io.ebean.DB
import io.ebean.Expr
import model.PracticeSession
import utils.ApplicationException
class PracticeSessionDAO {
@Throws(ApplicationException::class)
fun getPracticeSession(practice_session_id: Int): PracticeSession {
try {
return DB.find(PracticeSession::class.java).where(Expr.eq("id", practice_session_id)).findOne()!!
} catch (e:Exception){
throw ApplicationException("PracticeSession with id: $practice_session_id was not found. Returned error: $e")
}
}
}
和测试类
package dao.sqlserver
import io.ebean.DB
import io.ebean.Database
import io.ebean.Expr
import io.ebean.MockiEbean
import model.PracticeSession
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.BeforeEach
import org.mockito.Mockito
import org.mockito.Mockito.`when`
import io.ebeaninternal.server.core.DefaultServer
import org.mockito.InjectMocks
internal class PracticeSessionDAOTestMock {
lateinit var defaultServer : Database
lateinit var restoredServer : Database
@BeforeEach
fun setUp() {
defaultServer = DB.getDefault()
assertTrue(defaultServer is DefaultServer)
}
@AfterEach
fun tearDown() {
restoredServer = DB.getDefault()
assertTrue(restoredServer is DefaultServer)
}
@Test
fun getPracticeSession() {
val dbmock = Mockito.mock(Database::class.java)
val mockPracticeSession = PracticeSession()
mockPracticeSession.id=1
`when`(dbmock.find(PracticeSession::class.java).where(Expr.eq("id", 1)).findOne()!!).thenReturn(mockPracticeSession)
//val someBeanId = java.lang.Long.valueOf(47L)
//`when`(dbmock.getBeanId(null)).thenReturn(someBeanId)
val mockiEbean = MockiEbean.start(dbmock)
try{
val mockServer = DB.getDefault()
//val beanId: Any = mockServer.getBeanId(null)
//assertEquals(someBeanId, beanId);
val practiceSessionDAO = PracticeSessionDAO()
val practiceSession = practiceSessionDAO.getPracticeSession(1)
assertEquals(1, practiceSession.id)
} finally {
mockiEbean.restoreOriginal()
}
}
}
【问题讨论】:
-
Mockito 在“何时”函数中需要 ArugmentMatchers 不是吗?您可能需要输入 ArgumentMatchers.anyOrNull() 而不是 null
-
您正在使用数据库的模拟对象,即 dbmock。所以下面的调用将在模拟对象上进行,这不会导致实际调用。 dbmock.find(PracticeSession::class.java) 您需要为此调用提供要返回的对象,该对象是查询类型。类似于 when(dbmock.find(PracticeSession::class.java)).thenReturn(something) 它会导致空指针异常,因为您没有提供要返回的任何内容,因此它为上述调用返回 null 和 where(Expr.. ..) 在空对象上调用。我也被困在这里。如果您发现任何东西,请告诉我。
-
我带着这个 .thenReturn(mockPracticeSession) 返回。问题是 find() 没有返回任何东西,所以我也需要存根。我相信这是类似的问题:stackoverflow.com/questions/33124153/… Tho 我无法让任何一个解决方案发挥作用。当我有更多时间时,我必须对其进行测试。
标签: kotlin junit mockito dao ebean