Код: Выделить всё
public BigDecimal getBalance() {
try {
reentrantLock.lock();
return balance;
} finally {
reentrantLock.unlock();
}
}
public void deposit(BigDecimal amount, BigDecimal ceiling) {
try {
reentrantLock.lock();
BigDecimal newBalance = balance.add(amount.abs());
if (newBalance.compareTo(ceiling.abs()) = 0) {
balance = newBalance;
}
} finally {
reentrantLock.unlock();
}
}
public class DepositWithdrawAmount {
private final CeilingPort accountTypePort;
private final OverdraftPort overdraftPort;
private final AccountPort accountPort;
public DepositWithdrawAmount(AccountPort accountPort, CeilingPort accountTypePort, OverdraftPort overdraftPort) {
this.accountPort = accountPort;
this.accountTypePort = accountTypePort;
this.overdraftPort = overdraftPort;
}
public void forAccount(OperationType operationType, UUID accountNumber, BigDecimal amount) throws AccountOperationException {
BankAccount account = accountPort.get(accountNumber);
switch (operationType) {
case WITHDRAW -> {
BigDecimal overdraft = overdraftPort.forAccount(account);
account.withdraw(amount, overdraft);
}
case DEPOSIT -> {
BigDecimal ceiling = accountTypePort.forAccount(account);
account.deposit(amount,ceiling );
}
}
}
}
< /code>
И это мой тестовый класс < /p>
@ExtendWith(MockitoExtension.class)
public class DepositWithdrawConcurrentTest {
@Mock
CeilingPort ceilingPort;
@Mock
AccountPort accountPort;
@Mock
OverdraftPort overdraftPort;
@InjectMocks
DepositWithdrawAmount depositWithdrawAmount1;
@InjectMocks
DepositWithdrawAmount depositWithdrawAmount2;
BankAccount currentAccount;
BigDecimal initialBalance;
private static int numberOfOperations = 100;
@BeforeEach
void beforeEach() {
currentAccount = BankAccount.setupCurrentAccount();
initialBalance = currentAccount.getBalance();
when(accountPort.get(any())).thenReturn(currentAccount);
when(overdraftPort.forAccount(any())).thenReturn(BigDecimal.ZERO);
when(ceilingPort.forAccount(currentAccount)).thenReturn(BigDecimal.valueOf(Integer.MAX_VALUE));
}
@Test
void should_have_same_balance_after_equal_deposit_withdraw_concurrent() throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(10);
List tasks = new ArrayList();
for (int i = 0; i < 50; i++) {
tasks.add(() -> {
depositWithdrawAmount1
.forAccount(OperationType.DEPOSIT, currentAccount.getAccountId(), BigDecimal.valueOf(10));
return null;
});
}
for (int i = 0; i < 50; i++) {
tasks.add(() -> {
depositWithdrawAmount2
.forAccount(OperationType.WITHDRAW, currentAccount.getAccountId(), BigDecimal.valueOf(10));
return null;
});
}
executor.invokeAll(tasks);
executor.shutdown();
executor.awaitTermination(100, TimeUnit.SECONDS);
Assertions.assertEquals(initialBalance,currentAccount.getBalance());
}
}
< /code>
Я использую тест на intellij run run run, пока он не потерпит неудачу, и мой тест всегда не пройдет после примерно 20-30 пробежек.
В моем методе депозита /снятия я пытался использовать AtomisReference и называть сравнение < /code>, но все же тест не проходит.>
Подробнее здесь: https://stackoverflow.com/questions/797 ... ation-test
Мобильная версия