NullPointerException:测试将 Ebean 与 Mockito 和 JUnit、Kotlin 结合使用的 DAO class
NullPointerException: Testing DAO class that uses Ebean with Mockito and JUnit, Kotlin
所以我有一个用 kotlin 编写的非常基本的模型、dao 和控制器 classes。我正在使用 Ebean 连接服务和数据。我正在尝试为我的 DAO classes 创建单元测试。根据我的理解,单元测试实际上不应该调用数据库连接,即使我已经读到有些人已经将我的堆栈与 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 class.
中调用 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")
}
}
}
并测试 classes
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()
}
}
}
好的,所以我能够解决这个问题。这为我指出了正确的方向:
这是更正后的测试 class。我只需要模拟和存根一堆 classes 和函数。
package dao.sqlserver
import io.ebean.*
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
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
val mockQuery = Mockito.mock(Query::class.java)
val mockExprFactory = Mockito.mock(ExpressionFactory::class.java)
`when`(dbmock.find(PracticeSession::class.java)).thenReturn(mockQuery as Query<PracticeSession>?)
`when`(dbmock.getExpressionFactory()).thenReturn(mockExprFactory)
`when`(mockQuery.where(mockExprFactory.eq("id",1))).thenReturn(mockQuery)
`when`(mockQuery.findOne()).thenReturn(mockPracticeSession)
val mockiEbean = MockiEbean.start(dbmock)
try{
val practiceSessionDAO = PracticeSessionDAO()
val practiceSession = practiceSessionDAO.getPracticeSession(1)
assertEquals(1, practiceSession.id)
} finally {
mockiEbean.restoreOriginal()
}
}
}
所以我有一个用 kotlin 编写的非常基本的模型、dao 和控制器 classes。我正在使用 Ebean 连接服务和数据。我正在尝试为我的 DAO classes 创建单元测试。根据我的理解,单元测试实际上不应该调用数据库连接,即使我已经读到有些人已经将我的堆栈与 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 class.
中调用 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")
}
}
}
并测试 classes
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()
}
}
}
好的,所以我能够解决这个问题。这为我指出了正确的方向:
这是更正后的测试 class。我只需要模拟和存根一堆 classes 和函数。
package dao.sqlserver
import io.ebean.*
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
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
val mockQuery = Mockito.mock(Query::class.java)
val mockExprFactory = Mockito.mock(ExpressionFactory::class.java)
`when`(dbmock.find(PracticeSession::class.java)).thenReturn(mockQuery as Query<PracticeSession>?)
`when`(dbmock.getExpressionFactory()).thenReturn(mockExprFactory)
`when`(mockQuery.where(mockExprFactory.eq("id",1))).thenReturn(mockQuery)
`when`(mockQuery.findOne()).thenReturn(mockPracticeSession)
val mockiEbean = MockiEbean.start(dbmock)
try{
val practiceSessionDAO = PracticeSessionDAO()
val practiceSession = practiceSessionDAO.getPracticeSession(1)
assertEquals(1, practiceSession.id)
} finally {
mockiEbean.restoreOriginal()
}
}
}