Как написать junit для проверки параллелизма? - PullRequest
0 голосов
/ 23 мая 2019

Я довольно плохо знаком с 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 и т. Д. Все комбинации перестановок.

Как создать этот контрольный пример.Пожалуйста, помогите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...