java - 使用连接池使用 JUnit 对 DAO 类进行单元测试
问题描述
大家好,我是新来的,我需要您的帮助来使用 junit 对带有连接池的 DAO 类进行单元测试。这是 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();
}
}
这是我要测试的 DAO 类:
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;
}
}
首先从 doRetrieveAll 方法开始,我尝试做一个
@Test
public void doRetrieveAll_Success() throws SQLException {
assertNotNull(ordineDAO.doRetrieveAll());
}
但我需要知道如何设置 @BeforeAll 才能测试此方法。你能帮我理解如何正确设置测试类吗?谢谢
解决方案
您可以使用 PowerMockito 来实现这一点。我提到 PowerMockito 而不是 Mockito 的唯一原因是因为您的getConnection()
方法是静态的,并且使用 PowerMockito 更容易模拟静态方法
您需要添加以下依赖项才能使 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>
这是测试方法。
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();
}
}
}
我已经用注释行解释了代码。
我已经在 java 8 上自己测试了它以及上面提到的依赖项,一切对我来说都很好。
推荐阅读
- c# - 如何处理传输编码:使用 .NET Core HttpClient.PostAsync 下载文件时分块
- mysql - 如果存在则删除数据库,是否正确?
- python - Model.py 中的 Django 多个类
- fortran - Fortran 中的索引
- c++ - 创建引用第三方库的 C++ 库
- javascript - 如何使用 .text() 在文本旁边打印变量
- twilio - 暂停后使用 DTMF 音拨打分机 / Twilio Studio
- python - 将日期分配给下面的所有行,直到下一个日期
- javascript - 捕获单击和双击事件
- arrays - 如何在 MATLAB 中创建动态数组