我们如何为涉及与DB连接的方法编写单元测试?

Sun*_*lai 6 java unit-testing

我一直在询问有关为Web方法编写单元测试的问题,这些方法实际上与数据库通信并返回一些值.

比方说,我有一个名为"StudentInfoService"的Web服务.该网络服务提供API"getStudentInfo(studentid)"

这是一些示例代码段

public class StudentInfoService
{
    public StudentInfo getStudentInfo(long studentId) {
            //Communicates with DB and creates
            // StudentInfo object with necessary information
            // and returns it to the caller.
    }
}
Run Code Online (Sandbox Code Playgroud)

我们如何为这个方法getStudentInfo实际编写单元测试?一般来说,我们如何为涉及与资源(数据库,文件,JNDI等)连接的方法编写单元测试?

Vin*_*lds 4

首先,您示例中的类StudentInfoService不可测试,或者至少不容易测试。这是出于一个非常简单的原因 - 无法将数据库连接对象传递给类,至少在您列出的方法中是这样。

使类可测试需要您按以下方式构建类:

public class StudentInfoService
{
    private Connection conn;

    public StudentInfoService(Connection conn)
    {
        this.conn = conn;
    }

    public StudentInfo getStudentInfo(long studentId) {
            //Uses the conn object to communicate with DB and creates
            // StudentInfo object with necessary information
            // and returns it to the caller.
    }
}
Run Code Online (Sandbox Code Playgroud)

上面的代码允许通过构造函数进行依赖注入。如果更合适的话,您可以使用 setter 注入而不是构造函数注入,但它通常不适用于 DAO/Repository 类,因为如果没有连接,则不能将类视为完全形成。

依赖注入将允许您的测试用例创建与数据库的连接(这是您的测试类/系统的协作者),而不是让类/系统本身创建协作者对象。简而言之,您正在将建立数据库连接的机制与您的类解耦。如果您的类之前查找 JNDI 数据源然后创建连接,那么它将无法测试,除非您使用Apache Cactus或类似的框架(如Arquillian )将其部署到容器,或者使用嵌入式容器。通过将创建连接的问题与类隔离,您现在可以在类外部的单元测试中自由创建连接,并根据需要将它们提供给类,从而允许您在 Java SE 环境中运行测试。

这将使您能够使用面向数据库的单元测试框架,例如DbUnit,它允许您在每次测试之前将数据库设置为已知状态,然后将连接传递给类StudentInfoService,然后断言类的状态(以及测试后的协作者,即数据库)。

必须强调的是,当您对类进行单元测试时,您的类必须是唯一被测试的系统。像连接和数据源这样的项目只是可以而且应该被嘲笑的协作者。一些单元测试将使用内存数据库(例如H2HSQLDerby )进行单元测试,并使用数据库的生产等效安装进行集成和功能测试。

  • 不,您的服务或 DAO 不一定必须公开要测试的连接。连接(或者更好的是数据源)可以通过类路径资源找到,并且测试也可以通过类路径找到相同的资源。这样做的唯一优点是模拟连接,并测试其上调用的内容,但对于数据库测试,最好测试真正的数据库层(例如测试 SQL 语法)。 (2认同)