Я довольно плохо знаком с Junit и модульным тестированием, поэтому извините, если это квалифицируется как плохой вопрос.Я должен тестировать мой код для параллелизма.Я полностью понимаю, что не могу попросить кого-то сделать код для меня, но я остро нуждаюсь в тестовом примере, так как не понимаю, как действовать дальше.: (
Я создал API, который переводит деньги между двумя учетными записями. У нас есть значения fromAccountNumber, toAccountNumber, которые являются полями String, а сумма - BigDecimal. Детали счета хранятся в базе данных H2 (в памяти).
Я создал службу executor, но затем для нее требуется тип runnable, и я не могу сделать свой класс с логикой для передачи как runnable.
Также в коде безопасность потока, которой я достиг, используя Select.. для обновления (этот запрос: GET_BY_ID_QUERY_FOR_TRANSACTION) оператор при извлечении записей из БД.
Основная логика для перевода денег следующая:
public void transferMoney(String sender, String receiver, BigDecimal amount) throws TransferException {
Connection conn = null;
try {
conn = H2DataBase.getConnection();
checkIfAccountNumbersAreValid(sender, receiver);
AccountDetailsDTO fromAccountDto = getAccountByNumber(conn, sender);
AccountDetailsDTO toAccountDto = getAccountByNumber(conn, receiver);
if (null != fromAccountDto && null != toAccountDto) {
transfer(conn, fromAccountDto, toAccountDto, amount);
} else {
rollback(conn);
throw new TransferException("Transfer Failed. Please check the account numbers.",
Response.Status.BAD_REQUEST);
}
} catch (SQLException e) {
throw new TransferException("Transfer Failed !", Response.Status.INTERNAL_SERVER_ERROR);
} catch (ValidationException e) {
throw new TransferException(e.getMessage(), e.getStatus());
} finally {
closeConnection(conn);
}
}
private void transfer(Connection conn, AccountDetailsDTO fromAccountDto, AccountDetailsDTO toAccountDto,
BigDecimal transactionAmount) throws TransferException {
PreparedStatement preparedStatementInsertToTransaction = null;
PreparedStatement preparedStatementUpdateFromAccount = null;
PreparedStatement preparedStatementUpdateToAccount = null;
try {
checkToAndFromAreDifferent(fromAccountDto, toAccountDto);
checkAccountBalanceBeforeTransfer(fromAccountDto.getAccountBalance(), transactionAmount);
fromAccountDto.setAccountBalance(fromAccountDto.getAccountBalance().subtract(transactionAmount));
toAccountDto.setAccountBalance(toAccountDto.getAccountBalance().add(transactionAmount));
preparedStatementInsertToTransaction = conn
.prepareStatement(DBQueryUtility.INSERT_INTO_TRANSACTION_TABLE_QUERY);
preparedStatementInsertToTransaction.setString(1, fromAccountDto.getAccountNumber());
preparedStatementInsertToTransaction.setString(2, toAccountDto.getAccountNumber());
preparedStatementInsertToTransaction.setBigDecimal(3, transactionAmount);
preparedStatementInsertToTransaction.executeUpdate();
preparedStatementUpdateFromAccount = conn.prepareStatement(DBQueryUtility.UPDATE_BANK_ACCOUNT_TABLE_QUERY);
preparedStatementUpdateFromAccount.setBigDecimal(1, fromAccountDto.getAccountBalance());
preparedStatementUpdateFromAccount.setString(2, fromAccountDto.getAccountNumber());
preparedStatementUpdateFromAccount.executeUpdate();
preparedStatementUpdateToAccount = conn.prepareStatement(DBQueryUtility.UPDATE_BANK_ACCOUNT_TABLE_QUERY);
preparedStatementUpdateToAccount.setBigDecimal(1, toAccountDto.getAccountBalance());
preparedStatementUpdateToAccount.setString(2, toAccountDto.getAccountNumber());
preparedStatementUpdateToAccount.executeUpdate();
conn.commit();
} catch (ValidationException e) {
rollback(conn);
throw new TransferException(e.getMessage(), Response.Status.BAD_REQUEST);
} catch (RuntimeException | SQLException e) {
rollback(conn);
throw new TransferException("Transfer Failed", Response.Status.INTERNAL_SERVER_ERROR);
} finally {
closeConnection(conn);
closePreparedStatement(preparedStatementInsertToTransaction, preparedStatementUpdateFromAccount,
preparedStatementUpdateToAccount);
}
}
public void checkIfAccountNumbersAreValid(String sender, String receiver) throws ValidationException {
if (null == sender || null == receiver || sender.isEmpty() || receiver.isEmpty()) {
throw new ValidationException("Account details cannot be null or empty !", Response.Status.BAD_REQUEST);
}
}
@Override
public void checkToAndFromAreDifferent(AccountDetailsDTO fromAccountDto, AccountDetailsDTO toAccountDto)
throws ValidationException {
if (toAccountDto.getAccountNumber().equals(fromAccountDto.getAccountNumber())) {
throw new ValidationException("To and From accounts cannot be same !", Response.Status.BAD_REQUEST);
}
}
@Override
public void checkAccountBalanceBeforeTransfer(BigDecimal accountBalance, BigDecimal amount)
throws ValidationException {
if (accountBalance.compareTo(BigDecimal.ZERO) < 0 || accountBalance.compareTo(amount) < 0) {
throw new ValidationException("Low account balance. Cannot initiate transfer !",
Response.Status.BAD_REQUEST);
}
}
public AccountDetailsDTO getAccountByNumber(Connection conn, String accountNumber) throws TransferException {
AccountDetailsDTO detailsDTO = null;
try {
PreparedStatement preparedStatement = conn.prepareStatement(DBQueryUtility.GET_BY_ID_QUERY_FOR_TRANSACTION);
preparedStatement.setString(1, accountNumber);
ResultSet rs = preparedStatement.executeQuery();
while (rs.next()) {
detailsDTO = DBQueryUtility.extractAccountDtoFromResultSet(rs);
}
} catch (SQLException e) {
throw new TransferException("Get by account number failed ! Try again.",
Response.Status.INTERNAL_SERVER_ERROR);
}
return detailsDTO;
}
Я хочу создать тестовый сценарий, в которомЯ могу запустить 100 потоков, и каждый поток переводит сумму с одного счета на другой. Предположим, у нас есть 3 счета: 1,2,3 каждый с балансом 1000 $.
, поэтому 1 поток должен попытаться перенести от 1 до2, затем второй поток делает 2,1, затем 3,1 и т. Д. Все комбинации перестановок.
Как создать этот контрольный пример.Пожалуйста, помогите.