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()
        }

    }
}