Прежде всего, похоже, что вы не показываете использование реального кода.Например, вы добавили private static void getDbConn()
, но код вызывает conn = getConnection(...)
, переменная conn
нигде не объявлена и т. Д. Это затрудняет реальную помощь в решении вашей проблемы.
Глядя на свой модульный тест,вы хотите смоделировать экземпляры определенных классов, используемых PaytPaytmBilling, таких как DataSource, Connection и PreparedStatement.Они называются «зависимостями».
Для этого вам нужно изменить PaytPaytmBilling, чтобы эти зависимости были «введены» (см. Внедрение зависимости ).Это означает, что они предоставляются PaytPaytmBilling через конструктор или установщик (или с некоторыми платформами, просто добавляя аннотацию к полю).
В текущем коде зависимости получены самим PaytPaytmBilling (например, путем вызовастатический метод, или создание нового экземпляра), и они не могут быть смоделированы (кроме как через какие-то фреймворки черной магии, в которые я не советую вам сейчас углубляться).
Чтобы написать хорошие модульные тесты, вынеобходимо написать (или реорганизовать) код для тестирования, что означает, что зависимости вводятся, а не получаются внутри класса.Также избегайте статических методов и данных (с константами все в порядке), они плохо работают с внедрением зависимостей и тестируемым кодом.
Так, например, DataSource может быть внедрен через конструктор, например так:
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 или использовать попробуйте ресурсы .В вашем текущем коде ресурсы не будут закрыты, если во время обработки ресурсов произойдет исключение:
Connection conn = dataSource.getConnection("userId", "passwd", "url");
PreparedStatement pStatement = conn.prepareStatement(childSql);
try {
// processing steps
}
finally {
pStatement.close();
conn.close();
}
Или try-with-resources:
try (Connection conn = dataSource.getConnection("userId", "passwd", "url"),
PreparedStatement pStatement = conn.prepareStatement(childSql)) {
// processing steps
}
Поскольку Connection и PreparedStatement реализуют AutoCloseable интерфейс они будут закрыты автоматически, когда заканчивается блок try.Это возможно начиная с Java 7.