1 package de.aikiit.bilanzanalyser.upload;
2
3 import de.aikiit.bilanzanalyser.entity.BilanzRow;
4 import de.aikiit.bilanzanalyser.entity.database.BilanzRowEntity;
5 import de.aikiit.bilanzanalyser.entity.database.CategoryEntity;
6 import de.aikiit.bilanzanalyser.entity.database.PaymentEntity;
7 import de.aikiit.bilanzanalyser.entity.database.ShopEntity;
8 import de.aikiit.bilanzanalyser.entity.database.SourceEntity;
9 import de.aikiit.bilanzanalyser.entity.database.repository.BilanzRowRepository;
10 import de.aikiit.bilanzanalyser.entity.database.repository.CategoryRepository;
11 import de.aikiit.bilanzanalyser.entity.database.repository.PaymentRepository;
12 import de.aikiit.bilanzanalyser.entity.database.repository.ShopRepository;
13 import de.aikiit.bilanzanalyser.entity.database.repository.SourceRepository;
14 import de.aikiit.bilanzanalyser.reader.BilanzRowParserResult;
15 import org.junit.jupiter.api.Test;
16 import org.junit.jupiter.api.extension.ExtendWith;
17 import org.mockito.InjectMocks;
18 import org.mockito.Mock;
19 import org.mockito.junit.jupiter.MockitoExtension;
20 import org.springframework.dao.DataIntegrityViolationException;
21
22 import java.math.BigDecimal;
23 import java.time.LocalDate;
24 import java.util.List;
25 import java.util.Optional;
26
27 import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
28 import static org.mockito.ArgumentMatchers.any;
29 import static org.mockito.Mockito.mock;
30 import static org.mockito.Mockito.times;
31 import static org.mockito.Mockito.verify;
32 import static org.mockito.Mockito.when;
33
34 @ExtendWith(MockitoExtension.class)
35 class UploadAnalysisServiceTest {
36
37 @Mock
38 private BilanzRowRepository bilanzRowRepository;
39 @Mock
40 private ShopRepository shopRepository;
41 @Mock
42 private PaymentRepository paymentRepository;
43 @Mock
44 private CategoryRepository categoryRepository;
45 @Mock
46 private SourceRepository sourceRepository;
47
48 @InjectMocks
49 private UploadAnalysisService service;
50
51 @Test
52 void getOrCreatePayment_shouldHandleConcurrentInsert() {
53 when(paymentRepository.findByName("Cards")).thenReturn(Optional.empty())
54 .thenReturn(Optional.of(new PaymentEntity()));
55
56 when(paymentRepository.save(any())).thenThrow(DataIntegrityViolationException.class);
57
58 PaymentEntity result = service.getOrCreatePayment("Cards");
59
60 assertThat(result).isNotNull();
61
62 verify(paymentRepository, times(2)).findByName("Cards");
63 }
64
65 @Test
66 void replaceIfEmpty_shouldReplaceNullAndBlank() {
67 assertThat(service.replaceIfEmpty(null)).isEqualTo("<empty>");
68 assertThat(service.replaceIfEmpty(" ")).isEqualTo("<empty>");
69 assertThat(service.replaceIfEmpty(" value ")).isEqualTo("value");
70 }
71
72 @Test
73 void flushDataIntoDatabase_shouldSaveRows() {
74 BilanzRow row = mock(BilanzRow.class);
75 when(row.getDate()).thenReturn(LocalDate.now());
76 when(row.getAmount()).thenReturn(BigDecimal.TEN);
77 when(row.getDescription()).thenReturn("desc");
78 when(row.getShop()).thenReturn("shop");
79 when(row.getPayment()).thenReturn("cash");
80 when(row.getCategory()).thenReturn("food");
81 when(row.getSource()).thenReturn("app");
82
83 BilanzRowParserResult result = mock(BilanzRowParserResult.class);
84 when(result.rows()).thenReturn(List.of(row));
85
86 when(shopRepository.findByName(any())).thenReturn(Optional.of(new ShopEntity()));
87 when(paymentRepository.findByName(any())).thenReturn(Optional.of(new PaymentEntity()));
88 when(categoryRepository.findByName(any())).thenReturn(Optional.of(new CategoryEntity()));
89 when(sourceRepository.findByName(any())).thenReturn(Optional.of(new SourceEntity()));
90
91 service.flushDataIntoDatabase(result);
92
93 verify(bilanzRowRepository).save(any(BilanzRowEntity.class));
94 }
95 }