首页 > 解决方案 > 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()
        }

    }
}

标签: kotlinjunitmockitodaoebean

解决方案


好的,所以我能够解决这个问题。这为我指明了正确的方向: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()
        }

    }
}

推荐阅读