使用 DAO 和 Web 服务的数据库插入方法的 Junit 测试用例

Posted

技术标签:

【中文标题】使用 DAO 和 Web 服务的数据库插入方法的 Junit 测试用例【英文标题】:Junit test case for database insert method with DAO and web service 【发布时间】:2013-04-22 03:03:02 【问题描述】:

我正在实施一个基于网络服务的大学管理系统。该系统将某些课程添加到数据库中。下面是我正在使用的代码。

Course.java

public class Course 

    private String courseName;
    private String location;
    private String courseId;


       public String getCourseId()
               
        return courseId;
            

    public void setCourseId(String courseId) 
        this.courseId = courseId;
    

    public String getCourseName() 
        return courseName;
    

    public void setCourseName(String courseName) 
        this.courseName = courseName;
    

        public String getLocation() 
        return location;
    
    public void setLocation(String location) 
        this.location = location;
    

那么另一个文件如下

CourseDaoImpl.java

public class CourseDaoImpl implements IDao 
   Connection conn = null;
   Statement stmt = null;

public CourseDaoImpl()

try 
    Class.forName("com.mysql.jdbc.Driver").newInstance();
    conn = DriverManager.getConnection(
            "jdbc:mysql://localhost:3306/univesitydb", "root", "root");
    stmt = conn.createStatement();

    if (!conn.isClosed())
        System.out.println("Successfully connectiod");
 catch (SQLException e) 
    e.printStackTrace();
 catch (InstantiationException e) 
    e.printStackTrace();
 catch (IllegalAccessException e) 
    e.printStackTrace();
 catch (ClassNotFoundException e) 
    e.printStackTrace();



      @Override
  public String add(Object object) 

Course c = (Course) object ;

String courseId = c.getCourseId();
String courseName = c.getCourseName();
String location = c.getLocation();

String result = "";
int rowcount;

try 
    String query = "Insert into course (courseId,courseName,location) values"
            + " ('"
            + courseId
            + "', '"
            + courseName
            + "', '"
            + location
            + "')";
    rowcount = stmt.executeUpdate(query);
    if (rowcount > 0) 
        result = "true";
        System.out.println("Course inserted successful");
     else 
        result = "false:The data could not be inserted in the databse";
    
 catch (SQLException e) 
    e.printStackTrace();


return result;

第三个是如下的Web服务文件,它与前两个交互并将数据添加到数据库中。

CourseService.java

package edu.service;

          import edu.dao.IDao;
          import edu.dao.impl.CourseDaoImpl;
          import edu.db.entity.Course;

       public class CourseService 

     public String addCourse(String courseId, String courseName, String location)
       
       Course c = new Course();
       c.setCourseId(courseId);
       c.setCourseName(courseName);
       c.setLocation(location);     
       IDao dao = new CourseDaoImpl();
       return dao.add(c);   
     

看看我的代码清单,任何人都可以建议我如何为我的 add 方法编写测试用例。我完全是 JAVA 的初学者,我在朋友的帮助下学习了这个 java 部分,现在需要为我的数据库方法实现 Junit 测试,比如上面的添加课程。

请提出一些我可以学习、阅读和使用的东西来为我的数据库方法实施 Junit 测试。

【问题讨论】:

【参考方案1】:

这是一个在 spring 项目中使用 junit 的示例 dao 测试。

import java.util.List;

import junit.framework.Assert;

import org.jboss.tools.example.springmvc.domain.Member;
import org.jboss.tools.example.springmvc.repo.MemberDao;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.transaction.annotation.Transactional;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:test-context.xml",
"classpath:/META-INF/spring/applicationContext.xml")
@Transactional
@TransactionConfiguration(defaultRollback=true)
public class MemberDaoTest

    @Autowired
    private MemberDao memberDao;

    @Test
    public void testFindById()
    
        Member member = memberDao.findById(0l);

        Assert.assertEquals("John Smith", member.getName());
        Assert.assertEquals("john.smith@mailinator.com", member.getEmail());
        Assert.assertEquals("2125551212", member.getPhoneNumber());
        return;
    

    @Test
    public void testFindByEmail()
    
        Member member = memberDao.findByEmail("john.smith@mailinator.com");

        Assert.assertEquals("John Smith", member.getName());
        Assert.assertEquals("john.smith@mailinator.com", member.getEmail());
        Assert.assertEquals("2125551212", member.getPhoneNumber());
        return;
    

    @Test
    public void testRegister()
    
        Member member = new Member();
        member.setEmail("jane.doe@mailinator.com");
        member.setName("Jane Doe");
        member.setPhoneNumber("2125552121");

        memberDao.register(member);
        Long id = member.getId();
        Assert.assertNotNull(id);

        Assert.assertEquals(2, memberDao.findAllOrderedByName().size());
        Member newMember = memberDao.findById(id);

        Assert.assertEquals("Jane Doe", newMember.getName());
        Assert.assertEquals("jane.doe@mailinator.com", newMember.getEmail());
        Assert.assertEquals("2125552121", newMember.getPhoneNumber());
        return;
    

    @Test
    public void testFindAllOrderedByName()
    
        Member member = new Member();
        member.setEmail("jane.doe@mailinator.com");
        member.setName("Jane Doe");
        member.setPhoneNumber("2125552121");
        memberDao.register(member);

        List<Member> members = memberDao.findAllOrderedByName();
        Assert.assertEquals(2, members.size());
        Member newMember = members.get(0);

        Assert.assertEquals("Jane Doe", newMember.getName());
        Assert.assertEquals("jane.doe@mailinator.com", newMember.getEmail());
        Assert.assertEquals("2125552121", newMember.getPhoneNumber());
        return;
    

【讨论】:

在测试方法testRegister()中你使用的是DAO方法Member newMember = memberDao.findById(id),在执行memberDao.register(member)之后这是正确的做法吗?我认为您必须尝试获取数据库值并断言这些值。因为来自memberDao.findById(id) 的任何错误都可能对您的testRegister() 方法产生副作用。 @HariKrishnaGanji 我认为这是对的。通过使用findById(id),在调用register 之后,您实际上是在测试findById 而不是register。这可能会影响register 无法输入某些值(错误)并且findById 返回一些默认值(错误),因此可能不会被捕获。 谁能解释一下 - 什么是“classpath:test-context.xml”条目,该文件中应该包含什么? 我有一点疑问。在这种情况下,当我们每次构建项目时,值都会插入到数据库的所有表中。 (考虑到所有插入方法都有测试用例。)可能有多个测试用例,每个构建都会将值插入数据库。我不认为这会是一件好事。(在生产环境中) @Crocode,只是一个想法。如果成功,首先运行 testFindById() 的测试用例,然后我们只需要运行 testRegister() 的测试。我们可以这样做吗?无论如何,如果使用 testFindById() 获取数据失败,构建将不会成功。【参考方案2】:

您的类的设计会使测试它们变得困难。在您的方法中使用硬编码的连接字符串或使用new 实例化协作者可以被视为测试反模式。看看DependencyInjection 模式。像 Spring 这样的框架在这​​里可能会有所帮助。

要测试您的 DAO,您需要在单元测试中控制数据库连接。所以你要做的第一件事就是将它从你的 DAO 中提取到一个类中,你可以模拟或指向一个特定的测试数据库,你可以在测试运行之前和之后设置和检查它。

测试 db/DAO 代码的技术解决方案可能是 dbunit。您可以在无模式 XML 中定义您的测试数据,并让 dbunit 将其填充到您的测试数据库中。但是您仍然必须自己连接所有内容。但是,对于 Spring,您可以使用 spring-test-dbunit 之类的东西,它为您提供了很多杠杆作用和额外的工具。

当您称自己为初学者时,我怀疑这一切都非常令人生畏。您应该问问自己是否真的需要测试您的数据库代码。如果不是,您至少应该重构您的代码,以便您可以轻松地模拟所有数据库访问。对于一般的模拟,请查看Mockito。

【讨论】:

感谢您的帮助,即使我从未与 Springs 合作过。我不太清楚我是否真的应该测试我的代码,但我的项目合作伙伴需要这样做,我被分配了这样做的任务。任何方式感谢您的帮助。我会期待的。【参考方案3】:
@Test
public void testSearchManagementStaff() throws SQLException

    boolean res=true;
    ManagementDaoImp mdi=new ManagementDaoImp();
    boolean b=mdi.searchManagementStaff("abc@gmail.com"," 123456");
    assertEquals(res,b);

【讨论】:

【参考方案4】:

/*

公共类 UserDAO

public boolean insertUser(UserBean u) 
    boolean flag = false;
    MySqlConnection msq = new MySqlConnection();
    try 

        String sql = "insert into regis values(?,?,?,?,?)";

        Connection connection = msq.getConnection();
        PreparedStatement statement = null;
        statement = (PreparedStatement) connection.prepareStatement(sql);
        statement.setString(1, u.getname());
        statement.setString(2, u.getlname());
        statement.setString(3, u.getemail());
        statement.setString(4, u.getusername());
        statement.setString(5, u.getpasswords());
        statement.executeUpdate();

        flag = true;
     catch (Exception e) 
     finally 
        return flag;
    



public String userValidate(UserBean u) 
    String login = "";
    MySqlConnection msq = new MySqlConnection();
    try 
        String email = u.getemail();
        String Pass = u.getpasswords();

        String sql = "SELECT name FROM regis WHERE email=? and passwords=?";
        com.mysql.jdbc.Connection connection = msq.getConnection();
        com.mysql.jdbc.PreparedStatement statement = null;
        ResultSet rs = null;
        statement = (com.mysql.jdbc.PreparedStatement) connection.prepareStatement(sql);
        statement.setString(1, email);
        statement.setString(2, Pass);
        rs = statement.executeQuery();
        if (rs.next()) 
            login = rs.getString("name");
         else 
            login = "false";
        

     catch (Exception e) 
     finally 
        return login;
    


public boolean getmessage(UserBean u) 
    boolean flag = false;
    MySqlConnection msq = new MySqlConnection();
    try 


        String sql = "insert into feedback values(?,?)";

        Connection connection = msq.getConnection();
        PreparedStatement statement = null;
        statement = (PreparedStatement) connection.prepareStatement(sql);
        statement.setString(1, u.getemail());
        statement.setString(2, u.getfeedback());
        statement.executeUpdate();

        flag = true;
     catch (Exception e) 
     finally 
        return flag;
    



public boolean insertOrder(cartbean u) 
    boolean flag = false;
    MySqlConnection msq = new MySqlConnection();
    try 

        String sql = "insert into cart (product_id, email, Tprice, quantity) values (?,?,2000,?)";

        Connection connection = msq.getConnection();
        PreparedStatement statement = null;
        statement = (PreparedStatement) connection.prepareStatement(sql);
        statement.setString(1, u.getpid());
        statement.setString(2, u.getemail());
        statement.setString(3, u.getquantity());

        statement.executeUpdate();

        flag = true;
     catch (Exception e) 
        System.out.print("hi");
     finally 
        return flag;
    


【讨论】:

以上是关于使用 DAO 和 Web 服务的数据库插入方法的 Junit 测试用例的主要内容,如果未能解决你的问题,请参考以下文章

在 Android 项目上实现 DAO 模式

域、DAO 和服务层

如何在使用 jooq 生成的 dao 插入/更新后获取插入/更新的对象

单元测试 DAO

使用 DAO 模式

dao 的插入和更新方法不起作用