gpt4 book ai didi

java - Mockito - 如何避免将数据插入数据库?

转载 作者:行者123 更新时间:2023-11-30 06:02:11 26 4
gpt4 key购买 nike

我们如何为下面的代码编写mockito?它是用普通的 JDBC 编写的。我需要创建一个包含 main 方法的所有代码的模拟(它驱动更新数据的所有逻辑)。

我真的需要帮助来模拟避免插入实际数据。有人可以指导我吗?

public class PaytPaytmBilling { 
private static Category logger = Category.getInstance(PaytPaytmBilling.class);
private static InputStream inputS = XY.class.getResourceAsStream("/paytm.properties");

private static final INSERT_QUERY = "INSERT STATEMENT";


private static void insertPaytPaytmBilling(ArrayList allPaytPaytmBill) throws Exception{

conn = getConnection(userId, passwd, prop.getProperty("databaseURL"));

String childSql = buildInsertPaytPaytmBillSql();

PreparedStatement pStatement = conn.prepareStatement(childSql);

for (int i=0; i<allPaytPaytmBill.size(); i++){
PaytPaytmBill PaytmBill = (PaytPaytmBill) allPaytPaytmBill.get(i);

pStatement.setString(1, PaytmBill.getXX());
pStatement.setString(2, PaytmBill.getYY());
pStatement.setString(3, PaytmBill.getAA());
pStatement.setLong(4, PaytmBill.getBB());
pStatement.setLong(5, PaytmBill.getCC));
pStatement.setString(6, PaytmBill.getDD());
pStatement.setInt(7, PaytmBill.getEE());
pStatement.setInt(8, PaytmBill.getFF());
pStatement.setString(9, "");
pStatement.setString(10, "");
pStatement.execute();
}
pStatement.close();
conn.close();
}

private static void getDbConn() throws Exception {
// Here get DB connection
}


public static void main(String[] args) throws Exception
{
ArrayList allPaytPaytmBill = new ArrayList();
XY.init();
getDbConn();
// This query reads data from other tables and creates the data..
String qmrString = qmr.buildQmrSql();

allPaytPaytmBill = qmr.getAllMemberData(qmrString);

insertPaytPaytmBilling(allPaytPaytmBill);
}
}

Mockito 测试类:

@RunWith(MockitoJUnitRunner.class)
public class PaytmBillingTest {
private static Category logger = Category.getInstance(PaytmBillingTest.class);

@Mock
private DataSource ds;

@Mock
private Connection c;

@Mock
private PreparedStatement stmt;

@Mock
private ResultSet rs;

private ArrayList<PaytmBill> allPaytmBill;

@Before
public void before() {
allPaytmBill = new ArrayList<>();
PaytmBill PaytmBill = new PaytmBill();
PaytmBill.setAA("1182");
PaytmBill.setBB("5122");
PaytmBill.setCC("201807");
PaytmBill.setDD(0L);
PaytmBill.setEE(100);
PaytmBill.setFF(0);
PaytmBill.setGG(0);
PaytmBill.setHH("A");
PaytmBill.setII(null);
PaytmBill.setJJ(null);

allPaytmBill.add(PaytmBill);
}

@Test
public void testPaytmBilling() {
PaytmBilling PaytmBilling = new PaytmBilling();

}
}

最佳答案

首先,看起来您没有显示使用真实的代码。例如,您添加了 private static void getDbConn() 但代码调用 conn = getConnection(...),变量 conn 未声明任何地方等等。这使得真正帮助您解决问题变得更加困难。

查看您的单元测试,您想要模拟 PaytPaytmBilling 使用的某些类的实例,例如 DataSource、Connection 和PreparedStatement。这些称为“依赖项”。

为此,您需要更改 PaytPaytmBilling 以便“注入(inject)”这些依赖项(请参阅 Dependency Injection )。这意味着它们是通过构造函数或 setter (或者在某些框架中仅通过在字段上添加注释来提供)提供给 PaytPaytmBilling。

在当前代码中,依赖项是由 PaytPaytmBilling 本身获得的(例如,通过调用静态方法,或创建一个新实例),并且它们不能被模拟(除了通过一些我不建议您这样做的黑魔法模拟框架)现在就进入)。

要编写良好的单元测试,您需要编写(或重构)可测试的代码,这意味着依赖项是注入(inject)的,而不是在类内部获取的。还要避免静态方法和数据(常量即可),它们与依赖注入(inject)和可测试代码配合不好。

例如,数据源可以通过构造函数注入(inject),如下所示:

public class PaytPaytmBilling { 

private static final String CHILD_SQL = "SELECT bladiebla...";

private DataSource dataSource;

public PaytPaytmBilling(DataSource dataSource) {
this.dataSource = dataSource;
}

public void insertPaytPaytmBilling(List<PaytmBill> allPaytPaytmBill) {
// keeping the example simple here.
// don't use String literals for the parameters below but read
// them from Properties (which you can mock for the unit test)
Connection conn = dataSource.getConnection("userId", "passwd", "url");
PreparedStatement pStatement = conn.prepareStatement(CHILD_SQL);
for (int i=0; i<allPaytPaytmBill.size(); i++){
PaytPaytmBill PaytmBill = (PaytPaytmBill) allPaytPaytmBill.get(i);
pStatement.setString(1, PaytmBill.getXX());
pStatement.setString(2, PaytmBill.getYY());
pStatement.setString(3, PaytmBill.getAA());
// ...
pStatement.execute();
}
pStatement.close();
conn.close();
}

如果你像上面那样重写代码,你可以像这样测试它:

@RunWith(MockitoJUnitRunner.class)
public class PaytmBillingTest {

// this will cause Mockito to automatically create an instance
// and inject any mocks needed
@InjectMocks
private PaytmBilling instanceUnderTest;

@Mock
private DataSource dataSource;

// connection is not directly injected. It is obtained by calling
// the injected dataSource
@Mock
private Connection connection;

// preparedStatement is not directly injected. It is obtained by
// calling the connection, which was obtained by calling the
// injected dataSource
@Mock
private PreparedStatement preparedStatement;

private List<PaytmBill> allPaytmBill;

@Before
public void before() {
allPaytmBill = new ArrayList<>();
PaytmBill paytmBill = new PaytmBill();
paytmBill.setAA("1182");
paytmBill.setBB("5122");
paytmBill.setCC("201807");
paytmBill.setDD(0L);
paytmBill.setEE(100);
paytmBill.setFF(0);
paytmBill.setGG(0);
paytmBill.setHH("A");
paytmBill.setII(null);
paytmBill.setJJ(null);

allPaytmBill.add(PaytmBill);
}

@Test
public void testPaytmBilling() {
// given
when(dataSource.getConnection(anyString(), anyString(), anyString())).thenReturn(connection);
when(connection.prepareStatement(anyString())).thenReturn(preparedStatement);

// when
instanceUnderTest.insertPaytPaytmBilling(allPaytPaytmBill);

// then
verify(pStatement).setString(1, paytmBill.getXX());
verify(pStatement).setString(2, paytmBill.getYY());
verify(pStatement).setString(3, paytmBill.getAA());
// ...
verify(pStatement).execute();
verify(pStatement).close();
verify(connection).close();
}

关于您的代码的不相关建议:最好在finally block 中关闭资源,或使用try-with resources 。在当前代码中,如果在处理资源时发生异常,资源将不会被关闭:

Connection conn = dataSource.getConnection("userId", "passwd", "url");
PreparedStatement pStatement = conn.prepareStatement(childSql);
try {
// processing steps
}
finally {
pStatement.close();
conn.close();
}

或者尝试使用资源:

try (Connection conn = dataSource.getConnection("userId", "passwd", "url"),
PreparedStatement pStatement = conn.prepareStatement(childSql)) {

// processing steps
}

由于Connection和PreparedStatement实现了AutoCloseable当 try block 结束时,它们将自动关闭接口(interface)。从 Java 7 开始,这是可能的。

关于java - Mockito - 如何避免将数据插入数据库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52036023/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com