kotlin - NullPointerException:测试将 Ebean 与 Mockito 和 JUnit、Kotlin 一起使用的 DAO 类
问题描述
所以我有一个用 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 对象不同,因为只有一些函数在工作,即 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 - NullpointerException when stubbing Method
这是更正后的测试类。我只需要模拟和存根一堆类和函数。
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()
}
}
}
推荐阅读
- elasticsearch - logstash 转换为日期并仅使用 kibana 中的日期部分
- android - Flutter 键盘在 android 中隐藏文本字段,但在 iOS 中工作正常
- c# - 从 c# 库创建 .dll 并仅使特定函数可调用
- javascript - Angular 中的更新函数
- c++ - 每 0.25 秒做一次
- javascript - 如何在 ReactJS 中按对象数组过滤数组项?
- excel - 在 2 个范围之间选择数据
- highcharts - 将 Highchart 的 X 轴长度设置为从第一个数据点开始的 24 小时,显示少于 24 小时的数据
- c# - 从对象中的字符串数组中过滤字符串数组
- flutter - 使用 geolocator 和 provider 以及 flutter_maps 获取位置