Tests maybe

This commit is contained in:
Miroslav Vasilev 2024-01-14 22:09:28 +02:00
parent 9f741918d7
commit 126d9abf6b
4 changed files with 257 additions and 10 deletions

View file

@ -82,7 +82,7 @@ public class CategoryService {
processedTransactionCategoryRepository.deleteAllForTransactions(transactions.stream().map(AbstractEntity::getId).toList());
// Run each category's rules for all transactions in parallel to eachother
// Run each category's rules for all transactions concurrently to each other
final var futures = categorizations.stream()
.filter(Categorization::isRoot)
.collect(Collectors.groupingBy(Categorization::getCategoryId, HashMap::new, Collectors.toList()))
@ -118,7 +118,7 @@ public class CategoryService {
}))
.toArray(length -> (CompletableFuture<List<ProcessedTransactionCategory>>[]) new CompletableFuture[length]);
// Run them all in parallel
// Run them all concurrently/in parallel
final var ptcs = CompletableFuture.allOf(futures).thenApply((v) ->
Arrays.stream(futures)
.flatMap(future -> future.join().stream())
@ -128,15 +128,9 @@ public class CategoryService {
processedTransactionCategoryRepository.saveAllAndFlush(ptcs);
}
private Optional<ProcessedTransactionCategory> categorizeTransaction(final Collection<Categorization> allCategorizations, Categorization categorization, ProcessedTransaction processedTransaction) {
if (matchesRule(allCategorizations, categorization, processedTransaction)) {
return Optional.of(new ProcessedTransactionCategory(processedTransaction.getId(), categorization.getCategoryId()));
} else {
return Optional.empty();
}
}
private boolean matchesRule(final Collection<Categorization> allCategorizations, final Categorization categorization, final ProcessedTransaction processedTransaction) {
public boolean matchesRule(final Collection<Categorization> allCategorizations, final Categorization categorization, final ProcessedTransaction processedTransaction) {
return switch (categorization.getCategorizationRule()) {
// string operations
case STRING_REGEX, STRING_EQ, STRING_CONTAINS, STRING_IS_EMPTY -> {

View file

@ -0,0 +1,184 @@
package dev.mvvasilev.finances;
import dev.mvvasilev.finances.entity.Categorization;
import dev.mvvasilev.finances.enums.CategorizationRule;
import dev.mvvasilev.finances.enums.ProcessedTransactionField;
import org.apache.commons.lang3.RandomUtils;
import java.time.LocalDateTime;
public class CategorizationBuilder {
private Categorization categorization;
public CategorizationBuilder() {}
private CategorizationBuilder(Categorization categorization) {
this.categorization = categorization;
}
public static CategorizationBuilder withUser(int userId) {
var categorization = new Categorization();
categorization.setUserId(userId);
return new CategorizationBuilder(categorization);
}
public static CategorizationBuilder withCategory(long categoryId) {
var categorization = new Categorization();
categorization.setCategoryId(categoryId);
return new CategorizationBuilder(categorization);
}
public static CategorizationBuilder onField(ProcessedTransactionField field, CategorizationRule rule, boolean booleanValue) {
var categorization = new Categorization();
categorization.setRuleBasedOn(field);
categorization.setCategorizationRule(rule);
categorization.setBooleanValue(booleanValue);
return new CategorizationBuilder(categorization);
}
public static CategorizationBuilder onField(ProcessedTransactionField field, CategorizationRule rule, double numericValue) {
var categorization = new Categorization();
categorization.setRuleBasedOn(field);
categorization.setCategorizationRule(rule);
categorization.setNumericValue(numericValue);
return new CategorizationBuilder(categorization);
}
public static CategorizationBuilder onField(ProcessedTransactionField field, CategorizationRule rule, String stringValue) {
var categorization = new Categorization();
categorization.setRuleBasedOn(field);
categorization.setCategorizationRule(rule);
categorization.setStringValue(stringValue);
return new CategorizationBuilder(categorization);
}
public static CategorizationBuilder onBetween(ProcessedTransactionField field, double greaterThan, double lessThan) {
var categorization = new Categorization();
categorization.setRuleBasedOn(field);
categorization.setCategorizationRule(CategorizationRule.NUMERIC_BETWEEN);
categorization.setNumericGreaterThan(greaterThan);
categorization.setNumericLessThan(lessThan);
return new CategorizationBuilder(categorization);
}
public static CategorizationBuilder onBetween(ProcessedTransactionField field, LocalDateTime greaterThan, LocalDateTime lessThan) {
var categorization = new Categorization();
categorization.setRuleBasedOn(field);
categorization.setCategorizationRule(CategorizationRule.TIMESTAMP_BETWEEN);
categorization.setTimestampGreaterThan(greaterThan);
categorization.setTimestampLessThan(lessThan);
return new CategorizationBuilder(categorization);
}
public static CategorizationBuilder and(Categorization left, Categorization right) {
var categorization = new Categorization();
categorization.setCategorizationRule(CategorizationRule.AND);
categorization.setLeftCategorizationId(left.getId());
categorization.setRightCategorizationId(right.getId());
return new CategorizationBuilder(categorization);
}
public static CategorizationBuilder or(Categorization left, Categorization right) {
var categorization = new Categorization();
categorization.setCategorizationRule(CategorizationRule.OR);
categorization.setLeftCategorizationId(left.getId());
categorization.setRightCategorizationId(right.getId());
return new CategorizationBuilder(categorization);
}
public static CategorizationBuilder not(Categorization right) {
var categorization = new Categorization();
categorization.setCategorizationRule(CategorizationRule.NOT);
categorization.setRightCategorizationId(right.getId());
return new CategorizationBuilder(categorization);
}
public CategorizationBuilder user(int userId) {
categorization.setUserId(userId);
return this;
}
public CategorizationBuilder category(long categoryId) {
categorization.setCategoryId(categoryId);
return this;
}
public CategorizationBuilder on(ProcessedTransactionField field, CategorizationRule rule, boolean booleanValue) {
categorization.setRuleBasedOn(field);
categorization.setCategorizationRule(rule);
categorization.setBooleanValue(booleanValue);
return this;
}
public CategorizationBuilder on(ProcessedTransactionField field, CategorizationRule rule, double numericValue) {
categorization.setRuleBasedOn(field);
categorization.setCategorizationRule(rule);
categorization.setNumericValue(numericValue);
return this;
}
public CategorizationBuilder on(ProcessedTransactionField field, CategorizationRule rule, String stringValue) {
categorization.setRuleBasedOn(field);
categorization.setCategorizationRule(rule);
categorization.setStringValue(stringValue);
return this;
}
public CategorizationBuilder between(ProcessedTransactionField field, double greaterThan, double lessThan) {
categorization.setRuleBasedOn(field);
categorization.setCategorizationRule(CategorizationRule.NUMERIC_BETWEEN);
categorization.setNumericGreaterThan(greaterThan);
categorization.setNumericLessThan(lessThan);
return this;
}
public CategorizationBuilder between(ProcessedTransactionField field, LocalDateTime greaterThan, LocalDateTime lessThan) {
categorization.setRuleBasedOn(field);
categorization.setCategorizationRule(CategorizationRule.TIMESTAMP_BETWEEN);
categorization.setTimestampGreaterThan(greaterThan);
categorization.setTimestampLessThan(lessThan);
return this;
}
public Categorization build(boolean isRoot) {
categorization.setId(RandomUtils.nextLong());
categorization.setRoot(isRoot);
return categorization;
}
public Categorization build() {
categorization.setId(RandomUtils.nextLong());
categorization.setRoot(false);
return categorization;
}
}

View file

@ -0,0 +1,33 @@
package dev.mvvasilev.finances;
import dev.mvvasilev.finances.persistence.CategorizationRepository;
import dev.mvvasilev.finances.persistence.ProcessedTransactionCategoryRepository;
import dev.mvvasilev.finances.persistence.ProcessedTransactionRepository;
import dev.mvvasilev.finances.persistence.TransactionCategoryRepository;
import dev.mvvasilev.finances.services.CategoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
@SpringBootTest
public class CategoryServiceTests {
@MockBean
private TransactionCategoryRepository transactionCategoryRepository;
@MockBean
private CategorizationRepository categorizationRepository;
@MockBean
private ProcessedTransactionRepository processedTransactionRepository;
@MockBean
private ProcessedTransactionCategoryRepository processedTransactionCategoryRepository;
@Autowired
private CategoryService service;
public CategoryServiceTests() {
}
}

View file

@ -0,0 +1,36 @@
package dev.mvvasilev.finances.services;
import dev.mvvasilev.finances.CategorizationBuilder;
import dev.mvvasilev.finances.persistence.CategorizationRepository;
import dev.mvvasilev.finances.persistence.ProcessedTransactionCategoryRepository;
import dev.mvvasilev.finances.persistence.ProcessedTransactionRepository;
import dev.mvvasilev.finances.persistence.TransactionCategoryRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
class CategoryServiceTest {
@MockBean
private TransactionCategoryRepository transactionCategoryRepository;
@MockBean
private CategorizationRepository categorizationRepository;
@MockBean
private ProcessedTransactionRepository processedTransactionRepository;
@MockBean
private ProcessedTransactionCategoryRepository processedTransactionCategoryRepository;
@Autowired
private CategoryService service;
@Test
void matchesRule() {
}
}