Add various delete methods
Add delete methods for transactions and recurring transactions. Also add open/close methods for accounts. Add unit tests for all new methods. Also JAXB is no longer a provided dependency for build-war.
This commit is contained in:
5
pom.xml
5
pom.xml
@@ -166,11 +166,6 @@
|
|||||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.glassfish.jaxb</groupId>
|
|
||||||
<artifactId>jaxb-runtime</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</profile>
|
</profile>
|
||||||
</profiles>
|
</profiles>
|
||||||
|
|||||||
@@ -25,7 +25,11 @@ public enum ResponseReason {
|
|||||||
INVALID_LAST_OCCURRENCE_FORMAT(HttpStatus.INTERNAL_SERVER_ERROR),
|
INVALID_LAST_OCCURRENCE_FORMAT(HttpStatus.INTERNAL_SERVER_ERROR),
|
||||||
MISSING_RECURRING_TRANSACTION_ID(HttpStatus.INTERNAL_SERVER_ERROR),
|
MISSING_RECURRING_TRANSACTION_ID(HttpStatus.INTERNAL_SERVER_ERROR),
|
||||||
INVALID_RECURRING_TRANSACTION_ID(HttpStatus.INTERNAL_SERVER_ERROR),
|
INVALID_RECURRING_TRANSACTION_ID(HttpStatus.INTERNAL_SERVER_ERROR),
|
||||||
RECURRING_TRANSACTION_NOT_FOUND(HttpStatus.INTERNAL_SERVER_ERROR);
|
RECURRING_TRANSACTION_NOT_FOUND(HttpStatus.INTERNAL_SERVER_ERROR),
|
||||||
|
MISSING_TRANSACTION_ID(HttpStatus.INTERNAL_SERVER_ERROR),
|
||||||
|
INVALID_TRANSACTION_ID(HttpStatus.INTERNAL_SERVER_ERROR),
|
||||||
|
TRANSACTION_NOT_FOUND(HttpStatus.INTERNAL_SERVER_ERROR),
|
||||||
|
ACCOUNT_NOT_FOUND(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
|
|
||||||
private HttpStatus httpStatus;
|
private HttpStatus httpStatus;
|
||||||
|
|
||||||
|
|||||||
@@ -53,4 +53,34 @@ public class AccountController {
|
|||||||
|
|
||||||
return responseReason.toResponseEntity();
|
return responseReason.toResponseEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequestMapping("closeAccount")
|
||||||
|
public ResponseEntity closeAccount(String key) {
|
||||||
|
if (LOGGER.isDebugEnabled()) {
|
||||||
|
LOGGER.debug(String.format("/accounts/closeAccount got parameters: %s", key));
|
||||||
|
}
|
||||||
|
|
||||||
|
final ResponseReason responseReason = this.accountService.closeAccount(key);
|
||||||
|
|
||||||
|
if (LOGGER.isDebugEnabled()) {
|
||||||
|
LOGGER.debug(String.format("/accounts/closeAccount returns with %s", responseReason.name()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return responseReason.toResponseEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("openAccount")
|
||||||
|
public ResponseEntity openAccount(String key) {
|
||||||
|
if (LOGGER.isDebugEnabled()) {
|
||||||
|
LOGGER.debug(String.format("/accounts/openAccount got parameters: %s", key));
|
||||||
|
}
|
||||||
|
|
||||||
|
final ResponseReason responseReason = this.accountService.openAccount(key);
|
||||||
|
|
||||||
|
if (LOGGER.isDebugEnabled()) {
|
||||||
|
LOGGER.debug(String.format("/accounts/openAccount returns with %s", responseReason.name()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return responseReason.toResponseEntity();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,4 +80,23 @@ public class RecurringTransactionController {
|
|||||||
|
|
||||||
return responseReason.toResponseEntity();
|
return responseReason.toResponseEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequestMapping("deleteRecurringTransaction")
|
||||||
|
public ResponseEntity deleteRecurringTransaction(String recurringTransactionId) {
|
||||||
|
if (LOGGER.isDebugEnabled()) {
|
||||||
|
LOGGER.debug(String
|
||||||
|
.format("/recurringTransactions/deleteRecurringTransaction got parameters: %s",
|
||||||
|
recurringTransactionId));
|
||||||
|
}
|
||||||
|
|
||||||
|
final ResponseReason responseReason = this.recurringTransactionService
|
||||||
|
.deleteRecurringTransaction(recurringTransactionId);
|
||||||
|
|
||||||
|
if (LOGGER.isDebugEnabled()) {
|
||||||
|
LOGGER.debug(String
|
||||||
|
.format("/recurringTransactions/deleteRecurringTransaction returns with %s", responseReason.name()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return responseReason.toResponseEntity();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,4 +47,23 @@ public class TransactionController {
|
|||||||
|
|
||||||
return responseReason.toResponseEntity();
|
return responseReason.toResponseEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequestMapping("deleteTransaction")
|
||||||
|
public ResponseEntity deleteTransaction(String transactionId) {
|
||||||
|
if (LOGGER.isDebugEnabled()) {
|
||||||
|
LOGGER.debug(String
|
||||||
|
.format("/transactions/deleteTransaction got parameters: %s",
|
||||||
|
transactionId));
|
||||||
|
}
|
||||||
|
|
||||||
|
final ResponseReason responseReason = this.transactionService
|
||||||
|
.deleteTransaction(transactionId);
|
||||||
|
|
||||||
|
if (LOGGER.isDebugEnabled()) {
|
||||||
|
LOGGER.debug(String
|
||||||
|
.format("/transactions/deleteTransaction returns with %s", responseReason.name()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return responseReason.toResponseEntity();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,20 @@
|
|||||||
package de.financer.model;
|
package de.financer.model;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
public enum AccountStatus {
|
public enum AccountStatus {
|
||||||
/** Indicates that the account is open for bookings */
|
/** Indicates that the account is open for bookings */
|
||||||
OPEN,
|
OPEN,
|
||||||
/** Indicates that the account is closed and bookings to it are forbidden */
|
/** Indicates that the account is closed and bookings to it are forbidden */
|
||||||
CLOSED
|
CLOSED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method validates whether the given string represents a valid account status.
|
||||||
|
*
|
||||||
|
* @param status to check
|
||||||
|
* @return whether the given status represents a valid account status
|
||||||
|
*/
|
||||||
|
public static boolean isValidType(String status) {
|
||||||
|
return Arrays.stream(AccountStatus.values()).anyMatch((accountStatus) -> accountStatus.name().equals(status));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,4 +106,40 @@ public class AccountService {
|
|||||||
|
|
||||||
return ResponseReason.OK;
|
return ResponseReason.OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional(propagation = Propagation.REQUIRED)
|
||||||
|
public ResponseReason closeAccount(String key) {
|
||||||
|
return setAccountStatus(key, AccountStatus.CLOSED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(propagation = Propagation.REQUIRED)
|
||||||
|
public ResponseReason openAccount(String key) {
|
||||||
|
return setAccountStatus(key, AccountStatus.OPEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Visible for unit tests
|
||||||
|
/* package */ ResponseReason setAccountStatus(String key, AccountStatus accountStatus) {
|
||||||
|
if (!StringUtils.startsWith(key, "accounts.")) {
|
||||||
|
return ResponseReason.INVALID_ACCOUNT_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Account account = this.accountRepository.findByKey(key);
|
||||||
|
|
||||||
|
if (account == null) {
|
||||||
|
return ResponseReason.ACCOUNT_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
account.setStatus(accountStatus);
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.accountRepository.save(account);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
LOGGER.error(String.format("Could not update account status %s|%s", key, accountStatus.name()), e);
|
||||||
|
|
||||||
|
return ResponseReason.UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResponseReason.OK;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -387,4 +387,33 @@ public class RecurringTransactionService {
|
|||||||
recurringTransaction.getDescription(),
|
recurringTransaction.getDescription(),
|
||||||
recurringTransaction);
|
recurringTransaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional(propagation = Propagation.REQUIRED)
|
||||||
|
public ResponseReason deleteRecurringTransaction(String recurringTransactionId) {
|
||||||
|
ResponseReason response = ResponseReason.OK;
|
||||||
|
|
||||||
|
if (recurringTransactionId == null) {
|
||||||
|
return ResponseReason.MISSING_RECURRING_TRANSACTION_ID;
|
||||||
|
} else if (!NumberUtils.isCreatable(recurringTransactionId)) {
|
||||||
|
return ResponseReason.INVALID_RECURRING_TRANSACTION_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Optional<RecurringTransaction> optionalRecurringTransaction = this.recurringTransactionRepository
|
||||||
|
.findById(Long.valueOf(recurringTransactionId));
|
||||||
|
|
||||||
|
if (!optionalRecurringTransaction.isPresent()) {
|
||||||
|
return ResponseReason.RECURRING_TRANSACTION_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.recurringTransactionRepository.deleteById(Long.valueOf(recurringTransactionId));
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
LOGGER.error("Could not delete recurring transaction!", e);
|
||||||
|
|
||||||
|
response = ResponseReason.UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import de.financer.dba.TransactionRepository;
|
|||||||
import de.financer.model.Account;
|
import de.financer.model.Account;
|
||||||
import de.financer.model.RecurringTransaction;
|
import de.financer.model.RecurringTransaction;
|
||||||
import de.financer.model.Transaction;
|
import de.financer.model.Transaction;
|
||||||
|
import org.apache.commons.lang3.math.NumberUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -17,6 +18,7 @@ import java.time.LocalDate;
|
|||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.time.format.DateTimeParseException;
|
import java.time.format.DateTimeParseException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class TransactionService {
|
public class TransactionService {
|
||||||
@@ -168,4 +170,48 @@ public class TransactionService {
|
|||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional(propagation = Propagation.REQUIRED)
|
||||||
|
public ResponseReason deleteTransaction(String transactionId) {
|
||||||
|
ResponseReason response = ResponseReason.OK;
|
||||||
|
|
||||||
|
if (transactionId == null) {
|
||||||
|
return ResponseReason.MISSING_TRANSACTION_ID;
|
||||||
|
} else if (!NumberUtils.isCreatable(transactionId)) {
|
||||||
|
return ResponseReason.INVALID_TRANSACTION_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Optional<Transaction> optionalTransaction = this.transactionRepository
|
||||||
|
.findById(Long.valueOf(transactionId));
|
||||||
|
|
||||||
|
if (!optionalTransaction.isPresent()) {
|
||||||
|
return ResponseReason.TRANSACTION_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Transaction transaction = optionalTransaction.get();
|
||||||
|
final Account fromAccount = transaction.getFromAccount();
|
||||||
|
final Account toAccount = transaction.getToAccount();
|
||||||
|
final Long amount = transaction.getAmount();
|
||||||
|
|
||||||
|
// Invert the actual multiplier by multiplying with -1
|
||||||
|
// If we delete a transaction we do the inverse of the original transaction
|
||||||
|
fromAccount.setCurrentBalance(fromAccount.getCurrentBalance() + (this.ruleService
|
||||||
|
.getMultiplierFromAccount(fromAccount) * amount * -1));
|
||||||
|
toAccount.setCurrentBalance(toAccount.getCurrentBalance() + (this.ruleService
|
||||||
|
.getMultiplierToAccount(toAccount) * amount * -1));
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.transactionRepository.deleteById(Long.valueOf(transactionId));
|
||||||
|
|
||||||
|
this.accountService.saveAccount(fromAccount);
|
||||||
|
this.accountService.saveAccount(toAccount);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
LOGGER.error("Could not delete transaction!", e);
|
||||||
|
|
||||||
|
response = ResponseReason.UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public class RecurringTransactionService_getAllIntegrationTest {
|
|||||||
final List<RecurringTransaction> allRecurringTransactions = this.objectMapper
|
final List<RecurringTransaction> allRecurringTransactions = this.objectMapper
|
||||||
.readValue(mvcResult.getResponse().getContentAsByteArray(), new TypeReference<List<RecurringTransaction>>() {});
|
.readValue(mvcResult.getResponse().getContentAsByteArray(), new TypeReference<List<RecurringTransaction>>() {});
|
||||||
|
|
||||||
Assert.assertEquals(2, allRecurringTransactions.size());
|
Assert.assertEquals(3, allRecurringTransactions.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
package de.financer.service;
|
||||||
|
|
||||||
|
import de.financer.ResponseReason;
|
||||||
|
import de.financer.dba.AccountRepository;
|
||||||
|
import de.financer.model.Account;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.ArgumentMatchers;
|
||||||
|
import org.mockito.InjectMocks;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class AccountService_createAccountTest {
|
||||||
|
@InjectMocks
|
||||||
|
private AccountService classUnderTest;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private AccountRepository accountRepository;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_createAccount_INVALID_ACCOUNT_TYPE() {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to do
|
||||||
|
|
||||||
|
// Act
|
||||||
|
ResponseReason response = this.classUnderTest.createAccount(null, null);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.assertEquals(ResponseReason.INVALID_ACCOUNT_TYPE, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_createAccount_INVALID_ACCOUNT_KEY() {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to do
|
||||||
|
|
||||||
|
// Act
|
||||||
|
ResponseReason response = this.classUnderTest.createAccount(null, "BANK");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.assertEquals(ResponseReason.INVALID_ACCOUNT_KEY, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_createAccount_UNKNOWN_ERROR() {
|
||||||
|
// Arrange
|
||||||
|
Mockito.doThrow(new NullPointerException()).when(this.accountRepository).save(Mockito.any(Account.class));
|
||||||
|
|
||||||
|
// Act
|
||||||
|
ResponseReason response = this.classUnderTest.createAccount("accounts.test", "BANK");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.assertEquals(ResponseReason.UNKNOWN_ERROR, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_createAccount_OK() {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to do
|
||||||
|
|
||||||
|
// Act
|
||||||
|
ResponseReason response = this.classUnderTest.createAccount("accounts.test", "BANK");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.assertEquals(ResponseReason.OK, response);
|
||||||
|
Mockito.verify(this.accountRepository, Mockito.times(1))
|
||||||
|
.save(ArgumentMatchers.argThat((acc) -> "accounts.test".equals(acc.getKey())));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
package de.financer.service;
|
||||||
|
|
||||||
|
import de.financer.ResponseReason;
|
||||||
|
import de.financer.dba.AccountRepository;
|
||||||
|
import de.financer.model.Account;
|
||||||
|
import de.financer.model.AccountStatus;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.ArgumentMatchers;
|
||||||
|
import org.mockito.InjectMocks;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class AccountService_setAccountStatusTest {
|
||||||
|
@InjectMocks
|
||||||
|
private AccountService classUnderTest;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private AccountRepository accountRepository;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_setAccountStatus_INVALID_ACCOUNT_KEY() {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to do
|
||||||
|
|
||||||
|
// Act
|
||||||
|
ResponseReason response = this.classUnderTest.setAccountStatus(null, AccountStatus.CLOSED);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.assertEquals(ResponseReason.INVALID_ACCOUNT_KEY, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_setAccountStatus_ACCOUNT_NOT_FOUND() {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to do
|
||||||
|
|
||||||
|
// Act
|
||||||
|
ResponseReason response = this.classUnderTest.setAccountStatus("accounts.test", AccountStatus.CLOSED);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.assertEquals(ResponseReason.ACCOUNT_NOT_FOUND, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_setAccountStatus_UNKNOWN_ERROR() {
|
||||||
|
// Arrange
|
||||||
|
Mockito.when(this.accountRepository.findByKey(Mockito.anyString())).thenReturn(new Account());
|
||||||
|
Mockito.doThrow(new NullPointerException()).when(this.accountRepository).save(Mockito.any(Account.class));
|
||||||
|
|
||||||
|
// Act
|
||||||
|
ResponseReason response = this.classUnderTest.setAccountStatus("accounts.test", AccountStatus.CLOSED);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.assertEquals(ResponseReason.UNKNOWN_ERROR, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_setAccountStatus_OK() {
|
||||||
|
// Arrange
|
||||||
|
Mockito.when(this.accountRepository.findByKey(Mockito.anyString())).thenReturn(new Account());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
ResponseReason response = this.classUnderTest.setAccountStatus("accounts.test", AccountStatus.CLOSED);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.assertEquals(ResponseReason.OK, response);
|
||||||
|
Mockito.verify(this.accountRepository, Mockito.times(1))
|
||||||
|
.save(ArgumentMatchers.argThat((acc) -> AccountStatus.CLOSED.equals(acc.getStatus())));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
package de.financer.service;
|
||||||
|
|
||||||
|
import de.financer.ResponseReason;
|
||||||
|
import de.financer.config.FinancerConfig;
|
||||||
|
import de.financer.dba.RecurringTransactionRepository;
|
||||||
|
import de.financer.model.RecurringTransaction;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.InjectMocks;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class RecurringTransactionService_deleteRecurringTransactionTest {
|
||||||
|
@InjectMocks
|
||||||
|
private RecurringTransactionService classUnderTest;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private AccountService accountService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private RuleService ruleService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private RecurringTransactionRepository recurringTransactionRepository;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private FinancerConfig financerConfig;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_deleteRecurringTransaction_MISSING_RECURRING_TRANSACTION_ID() {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to do
|
||||||
|
|
||||||
|
// Act
|
||||||
|
final ResponseReason response = this.classUnderTest.deleteRecurringTransaction(null);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.assertEquals(ResponseReason.MISSING_RECURRING_TRANSACTION_ID, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_deleteRecurringTransaction_INVALID_RECURRING_TRANSACTION_ID() {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to do
|
||||||
|
|
||||||
|
// Act
|
||||||
|
final ResponseReason response = this.classUnderTest.deleteRecurringTransaction("invalid");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.assertEquals(ResponseReason.INVALID_RECURRING_TRANSACTION_ID, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_deleteRecurringTransaction_RECURRING_TRANSACTION_NOT_FOUND() {
|
||||||
|
// Arrange
|
||||||
|
Mockito.when(this.recurringTransactionRepository.findById(Mockito.anyLong())).thenReturn(Optional.empty());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
final ResponseReason response = this.classUnderTest.deleteRecurringTransaction("123");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.assertEquals(ResponseReason.RECURRING_TRANSACTION_NOT_FOUND, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_deleteRecurringTransaction_UNKNOWN_ERROR() {
|
||||||
|
// Arrange
|
||||||
|
Mockito.when(this.recurringTransactionRepository.findById(Mockito.anyLong())).thenReturn(Optional.of(new RecurringTransaction()));
|
||||||
|
Mockito.doThrow(new NullPointerException()).when(this.recurringTransactionRepository).deleteById(Mockito.anyLong());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
final ResponseReason response = this.classUnderTest.deleteRecurringTransaction("123");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.assertEquals(ResponseReason.UNKNOWN_ERROR, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_deleteRecurringTransaction_OK() {
|
||||||
|
// Arrange
|
||||||
|
Mockito.when(this.recurringTransactionRepository.findById(Mockito.anyLong())).thenReturn(Optional.of(new RecurringTransaction()));
|
||||||
|
|
||||||
|
// Act
|
||||||
|
final ResponseReason response = this.classUnderTest.deleteRecurringTransaction("123");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.assertEquals(ResponseReason.OK, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
package de.financer.service;
|
||||||
|
|
||||||
|
import de.financer.ResponseReason;
|
||||||
|
import de.financer.config.FinancerConfig;
|
||||||
|
import de.financer.dba.TransactionRepository;
|
||||||
|
import de.financer.model.Account;
|
||||||
|
import de.financer.model.AccountType;
|
||||||
|
import de.financer.model.Transaction;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.*;
|
||||||
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class TransactionService_deleteTransactionTest {
|
||||||
|
@InjectMocks
|
||||||
|
private TransactionService classUnderTest;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private AccountService accountService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private RuleService ruleService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private TransactionRepository transactionRepository;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private FinancerConfig financerConfig;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
this.ruleService.afterPropertiesSet();
|
||||||
|
|
||||||
|
Mockito.when(this.ruleService.getMultiplierFromAccount(Mockito.any())).thenCallRealMethod();
|
||||||
|
Mockito.when(this.ruleService.getMultiplierToAccount(Mockito.any())).thenCallRealMethod();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_deleteRecurringTransaction_MISSING_TRANSACTION_ID() {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to do
|
||||||
|
|
||||||
|
// Act
|
||||||
|
final ResponseReason response = this.classUnderTest.deleteTransaction(null);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.assertEquals(ResponseReason.MISSING_TRANSACTION_ID, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_deleteRecurringTransaction_INVALID_TRANSACTION_ID() {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to do
|
||||||
|
|
||||||
|
// Act
|
||||||
|
final ResponseReason response = this.classUnderTest.deleteTransaction("invalid");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.assertEquals(ResponseReason.INVALID_TRANSACTION_ID, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_deleteRecurringTransaction_TRANSACTION_NOT_FOUND() {
|
||||||
|
// Arrange
|
||||||
|
Mockito.when(this.transactionRepository.findById(Mockito.anyLong())).thenReturn(Optional.empty());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
final ResponseReason response = this.classUnderTest.deleteTransaction("123");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.assertEquals(ResponseReason.TRANSACTION_NOT_FOUND, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_deleteRecurringTransaction_UNKNOWN_ERROR() {
|
||||||
|
// Arrange
|
||||||
|
Mockito.when(this.transactionRepository.findById(Mockito.anyLong()))
|
||||||
|
.thenReturn(Optional.of(createTransaction(AccountType.BANK, AccountType.EXPENSE)));
|
||||||
|
Mockito.doThrow(new NullPointerException()).when(this.transactionRepository).deleteById(Mockito.anyLong());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
final ResponseReason response = this.classUnderTest.deleteTransaction("123");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.assertEquals(ResponseReason.UNKNOWN_ERROR, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_deleteRecurringTransaction_OK() {
|
||||||
|
// Arrange
|
||||||
|
Mockito.when(this.transactionRepository.findById(Mockito.anyLong()))
|
||||||
|
.thenReturn(Optional.of(createTransaction(AccountType.BANK, AccountType.EXPENSE)));
|
||||||
|
|
||||||
|
// Act
|
||||||
|
final ResponseReason response = this.classUnderTest.deleteTransaction("123");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.assertEquals(ResponseReason.OK, response);
|
||||||
|
|
||||||
|
final InOrder inOrder = Mockito.inOrder(this.accountService);
|
||||||
|
|
||||||
|
inOrder.verify(this.accountService).saveAccount(ArgumentMatchers.argThat((Account arg) -> Long.valueOf(50000L).equals(arg.getCurrentBalance())));
|
||||||
|
inOrder.verify(this.accountService).saveAccount(ArgumentMatchers.argThat((Account arg) -> Long.valueOf(5000L).equals(arg.getCurrentBalance())));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Transaction createTransaction(AccountType fromType, AccountType toType) {
|
||||||
|
final Transaction transaction = new Transaction();
|
||||||
|
final Account fromAccount = new Account();
|
||||||
|
final Account toAccount = new Account();
|
||||||
|
|
||||||
|
transaction.setFromAccount(fromAccount);
|
||||||
|
transaction.setToAccount(toAccount);
|
||||||
|
transaction.setAmount(Long.valueOf(10000L));
|
||||||
|
|
||||||
|
fromAccount.setCurrentBalance(Long.valueOf(40000L));
|
||||||
|
toAccount.setCurrentBalance(Long.valueOf(15000L));
|
||||||
|
|
||||||
|
fromAccount.setType(fromType);
|
||||||
|
toAccount.setType(toType);
|
||||||
|
|
||||||
|
return transaction;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user