简体   繁体   English

使用连接池对带有 JUnit 的 DAO 类进行单元测试

[英]Unit test DAO classes with JUnit using a Connection Pool

Hi everyone i'm new here and i need your help to unit test with junit a DAO class with a connection pool.大家好,我是新来的,我需要您的帮助来使用 junit 和带有连接池的 DAO class 进行单元测试。 This is the ConPool:这是 ConPool:

public class ConPool {

private static DataSource datasource;

/**
 * {@return} Connection
 * {@throws} SQLException
 *     Ritorna la connessione al db.
 */

public static Connection getConnection() throws SQLException {
if (datasource == null) {
  PoolProperties p = new PoolProperties();
  p.setUrl("jdbc:mysql://localhost:3306/GameLand?serverTimezone="
          + TimeZone.getDefault().getID());
  p.setDriverClassName("com.mysql.cj.jdbc.Driver");
  p.setUsername("root");
  p.setPassword("basedidati");
  p.setMaxActive(100);
  p.setInitialSize(10);
  p.setMinIdle(10);
  p.setRemoveAbandonedTimeout(60);
  p.setRemoveAbandoned(true);
  datasource = new DataSource();
  datasource.setPoolProperties(p);
}
  return datasource.getConnection();
 }
}

and this is the DAO class that i want to test:这是我要测试的DAO class:

public class OrdineDAO {
/**
 * {@return} ArrayList of Ordine.
 */

public synchronized ArrayList<Ordine> doRetrieveAll() {

String query = "SELECT * FROM ordine";
ArrayList<Ordine> result = new ArrayList<Ordine>();

try (Connection conn = ConPool.getConnection()) {

  PreparedStatement ps = conn.prepareStatement(query);
  ResultSet rs = ps.executeQuery();
  while (rs.next()) {

    Ordine ord = new Ordine();
    ord.setConsegnato(rs.getBoolean("consegnato"));
    ord.setDataOra(rs.getString("dataOra"));
    ord.setIdOrdine(rs.getInt("idOrdine"));
    ord.setIdProdotto(rs.getInt("idProdotto"));
    ord.setPrezzoFis(rs.getDouble("prezzoFis"));
    ord.setPrezzoDig(rs.getDouble("prezzoDig"));
    ord.setIva(rs.getDouble("iva"));
    ord.setQuantitaDigitale(rs.getInt("quantitaDigitale"));
    ord.setQuantitaFisico(rs.getInt("quantitaFisico"));
    ord.setIdUtente(rs.getInt("idUtente"));
    result.add(ord);

  }

} catch (SQLException e) {

  e.printStackTrace();

}


return result;
}
/**
 * {@param} id: int.
 * {@return} ArrayList of Ordine.
 */

public synchronized ArrayList<Ordine> doRetrieveByUser(int id) {

PreparedStatement ps = null;
String query = "SELECT * FROM ordine WHERE idUtente = ?";
ArrayList<Ordine> result = new ArrayList<Ordine>();

try (Connection conn = ConPool.getConnection()) {

  ps = conn.prepareStatement(query);
  ps.setInt(1, id);
  ResultSet rs = ps.executeQuery();
  while (rs.next()) {

    Ordine ord = new Ordine();
    ord.setConsegnato(rs.getBoolean("consegnato"));
    ord.setDataOra(rs.getString("dataOra"));
    ord.setIdOrdine(rs.getInt("idOrdine"));
    ord.setIdProdotto(rs.getInt("idProdotto"));
    ord.setPrezzoFis(rs.getDouble("prezzoFis"));
    ord.setPrezzoDig(rs.getDouble("prezzoDig"));
    ord.setIva(rs.getDouble("iva"));
    ord.setQuantitaDigitale(rs.getInt("quantitaDigitale"));
    ord.setQuantitaFisico(rs.getInt("quantitaFisico"));
    ord.setIdUtente(rs.getInt("idUtente"));
    result.add(ord);

  }

} catch (SQLException e) {

  e.printStackTrace();

}

return result;
}
/**
 * {@param} data1: String.
 * {@param} data2: String.
 * {@return} ArrayList of Ordine.
 */

public synchronized ArrayList<Ordine> doRetrieveByDate(String data1, String data2) {

PreparedStatement ps = null;
String query = "SELECT * FROM ordine WHERE dataOra >= ? AND dataOra <= ?";
ArrayList<Ordine> result = new ArrayList<Ordine>();

try (Connection conn = ConPool.getConnection()) {

  ps = conn.prepareStatement(query);
  ps.setString(1, data1);
  ps.setString(2, data2);
  ResultSet rs = ps.executeQuery();
  while (rs.next()) {

    Ordine ord = new Ordine();
    ord.setConsegnato(rs.getBoolean("consegnato"));
    ord.setDataOra(rs.getString("dataOra"));
    ord.setIdOrdine(rs.getInt("idOrdine"));
    ord.setIdProdotto(rs.getInt("idProdotto"));
    ord.setPrezzoFis(rs.getDouble("prezzoFis"));
    ord.setPrezzoDig(rs.getDouble("prezzoDig"));
    ord.setIva(rs.getDouble("iva"));
    ord.setQuantitaDigitale(rs.getInt("quantitaDigitale"));
    ord.setQuantitaFisico(rs.getInt("quantitaFisico"));
    ord.setIdUtente(rs.getInt("idUtente"));
    result.add(ord);

  }

} catch (SQLException e) {

  e.printStackTrace();

}

 return result;
 }

}

starting first with doRetrieveAll method, i tried to do a首先从 doRetrieveAll 方法开始,我尝试做一个

@Test
public void doRetrieveAll_Success() throws SQLException {
    assertNotNull(ordineDAO.doRetrieveAll());
}

But i need to know how to set the @BeforeAll in order to test this method.但我需要知道如何设置 @BeforeAll 才能测试此方法。 Can you please help me understanding how to set properly the test class?你能帮我理解如何正确设置测试 class 吗? Thank you谢谢

You can use PowerMockito to achieve this.您可以使用 PowerMockito 来实现这一点。 Only reason why I mentioned PowerMockito instead of Mockito is because your getConnection() method is static and it's easier to mock static methods using PowerMockito我提到 PowerMockito 而不是 Mockito 的唯一原因是因为您的getConnection()方法是 static 并且使用 PowerMockito 模拟 static 方法更容易

You need to add the below dependencies to get PowerMockito working.您需要添加以下依赖项才能使 PowerMockito 正常工作。

    <dependency>
      <groupId>org.powermock</groupId>
      <artifactId>powermock-module-junit4</artifactId>
      <version>1.6.4</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.powermock</groupId>
      <artifactId>powermock-api-mockito</artifactId>
      <version>1.6.4</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.powermock</groupId>
      <artifactId>powermock-module-junit4-rule</artifactId>
      <version>1.6.4</version>
      <scope>test</scope>
    </dependency>

Here is the Test method.这是测试方法。

import static org.mockito.Matchers.any;
import static org.powermock.api.mockito.PowerMockito.when;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest(ConPool.class)
public class OrdineDAOTest {

  @Mock
  private Connection c;

  @Mock
  private PreparedStatement stmt;

  @Mock
  private ResultSet rs;

  @Test
  public void testDoRetrieveAll() {
    try {
      //Mocking the Static ConPool Class 
      PowerMockito.mockStatic(ConPool.class);
      //Making the ConPool.getConnection() method to return Mocked Connection 
      when(ConPool.getConnection()).thenReturn(c);
      //Making the prepareStatement method to return Mocked PrepareStatement 
      when(c.prepareStatement(any(String.class))).thenReturn(stmt);
      // Mocking the Values in ResultSet 
      when(rs.getInt("idOrdine")).thenReturn(10); 
      //This means result set has only one set of result
      //Mocking rs.next() to return true first and then return false the second time
      when(rs.next()).thenReturn(true).thenReturn(false);
      //Making executeQuery() method to return mocked resultset
      when(stmt.executeQuery()).thenReturn(rs);

      OrdineDAO dao = new OrdineDAO();
      // Invoking the actual method from dao
      ArrayList<Ordine> list = dao.doRetrieveAll();
      //Comparing the expected vs actual
      Assert.assertEquals(1, list.size());
      Assert.assertEquals(10, list.get(0).getIdOrdine());
    } catch (Exception e) {
      e.printStackTrace();
    }

  }
}

I have explained the code with the commented lines.我已经用注释行解释了代码。

I have tested it myself on java 8 along with the above mentioned dependencies and everything works fine for me.我已经在 java 8 以及上面提到的依赖项上自己测试了它,一切对我来说都很好。

Great, It works fine.太好了,它工作正常。 thank you much.非常感谢。 I'd like to see how to create this test case using mockito, Also.我还想看看如何使用 mockito 创建这个测试用例。 when i will test the doRetrieveByUser and the doRetrieveByDate i don't know if i have to test the success/fail scenario (passing good/wrong arguments) or i can write these tests in the "same" way as the doRetrieveAll test case.当我将测试 doRetrieveByUser 和 doRetrieveByDate 时,我不知道是否必须测试成功/失败场景(传递好/错误的参数),或者我可以以与 doRetrieveAll 测试用例“相同”的方式编写这些测试。 Hope it is clear.希望很清楚。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM