简体   繁体   中英

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. This is the 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:

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

@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. Can you please help me understanding how to set properly the test class? Thank you

You can use PowerMockito to achieve this. 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

You need to add the below dependencies to get PowerMockito working.

    <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.

Great, It works fine. thank you much. I'd like to see how to create this test case using mockito, Also. 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. Hope it is clear.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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