Skip to content

Commit 20cadfc

Browse files
authored
feat: first approach for event tests (#166)
* feat: first approach for event tests * feat: added accounthandler duplicate test * chore: added postgres to gha * chore: merged build with tests and sonar gha * chore: removed tests from earthly build * chore: removed tests from earthly build * chore: add tests for resource * chore: add tests for resource * feat: add duplicate tests for blockchain publisher events
1 parent ca53fd8 commit 20cadfc

File tree

21 files changed

+830
-45
lines changed

21 files changed

+830
-45
lines changed

.github/workflows/build-with-tests.yaml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,19 @@ jobs:
3232

3333
- name: Test
3434
run: |
35-
./gradlew clean test
35+
./gradlew clean test jacocoTestReport
3636
- name: Spotless
3737
run : |
3838
./gradlew spotlessCheck
39+
- name: SonarCloud Scan
40+
env:
41+
SONAR_TOKEN: ${{ secrets.SONARCLOUD_TOKEN }}
42+
run: |
43+
./gradlew sonar \
44+
-Dsonar.host.url=https://sonarcloud.io \
45+
-Dsonar.organization=cardano-foundation \
46+
-Dsonar.projectKey=cardano-foundation_cf-lob-platform \
47+
-Dsonar.branch.name=${{ github.head_ref }}
3948
4049
# mutation-test:
4150
# needs: test

.github/workflows/sonar-cloud-report.yml

Lines changed: 0 additions & 35 deletions
This file was deleted.

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
FROM openjdk:21-jdk-slim AS build
22
WORKDIR /app
33
COPY . /app
4-
RUN ./gradlew clean build publishMavenJavaPublicationToLocalM2Repository
4+
RUN ./gradlew clean build publishMavenJavaPublicationToLocalM2Repository -x test
55

66
FROM scratch AS platform-library-m2-cache
77
COPY --from=build /root/.m2 /root/.m2

accounting_reporting_core/build.gradle.kts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,10 @@ dependencies {
1010
implementation(project(":blockchain_reader"))
1111
implementation(project(":organisation"))
1212
implementation(project(":support"))
13+
14+
testImplementation("org.springframework.boot:spring-boot-starter-data-jpa")
15+
testImplementation("org.springframework.modulith:spring-modulith-starter-test")
16+
testImplementation("org.springframework.modulith:spring-modulith-starter-core")
17+
testImplementation("org.springframework.modulith:spring-modulith-events-jdbc")
18+
testImplementation("org.springframework.boot:spring-boot-starter-validation")
1319
}

accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/domain/entity/reconcilation/ReconcilationEntity.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ public String getId() {
8787
@AttributeOverride(name = "transactionInternalNumber", column = @Column(name = "transaction_internal_number", nullable = false)),
8888
@AttributeOverride(name = "transactionEntryDate", column = @Column(name = "transaction_entry_date", nullable = false)),
8989
@AttributeOverride(name = "transactionType", column = @Column(name = "transaction_type", nullable = false)),
90-
@AttributeOverride(name = "amountLcySum", column = @Column(name = "amount_lcy_sum", nullable = false))
90+
@AttributeOverride(name = "amountLcySum", column = @Column(name = "amount_lcy_sum", nullable = false)),
91+
@AttributeOverride(name = "sourceDiff", column = @Column(name = "source_diff", nullable = false))
9192
})
9293
@Setter
9394
@Getter

accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/internal/TransactionReconcilationService.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,12 @@ public void createReconcilation(String reconcilationId,
6262
" to: {}",
6363
reconcilationId, from, to
6464
);
65-
66-
val reconcilationEntity = new ReconcilationEntity();
65+
Optional<ReconcilationEntity> entity = transactionReconcilationRepository.findById(reconcilationId);
66+
if(entity.isPresent()) {
67+
log.warn("Reconcilation already exists, reconcilationId: {}", reconcilationId);
68+
return;
69+
}
70+
ReconcilationEntity reconcilationEntity = new ReconcilationEntity();
6771
reconcilationEntity.setId(reconcilationId);
6872
reconcilationEntity.setOrganisationId(organisationId);
6973
reconcilationEntity.setStatus(ReconcilationStatus.CREATED);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package org.cardanofoundation.lob.app.accounting_reporting_core.config;
2+
3+
import java.math.BigDecimal;
4+
5+
import lombok.extern.slf4j.Slf4j;
6+
7+
import org.springframework.context.annotation.Bean;
8+
import org.springframework.context.annotation.Configuration;
9+
10+
import org.javers.core.Javers;
11+
import org.javers.core.JaversBuilder;
12+
13+
import org.cardanofoundation.lob.app.support.javers.LOBBigDecimalComparator;
14+
15+
@Configuration
16+
@Slf4j
17+
public class JaversConfig {
18+
19+
@Bean
20+
public Javers javers() {
21+
log.info("Creating Javers diff instance...");
22+
23+
return JaversBuilder.javers()
24+
.withPrettyPrint(true)
25+
.registerValue(BigDecimal.class, new LOBBigDecimalComparator())
26+
.build();
27+
}
28+
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package org.cardanofoundation.lob.app.accounting_reporting_core.config;
2+
3+
import javax.sql.DataSource;
4+
5+
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
6+
import org.springframework.context.annotation.Bean;
7+
import org.springframework.context.annotation.Configuration;
8+
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
9+
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
10+
11+
@Configuration
12+
@EnableJpaRepositories( { "org.cardanofoundation.lob", "org.springframework.modulith.events.jpa" } )
13+
public class JpaConfig {
14+
15+
@Bean
16+
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder, DataSource dataSource) {
17+
return builder
18+
.dataSource(dataSource)
19+
.packages("org.cardanofoundation.lob")
20+
.persistenceUnit("default")
21+
.build();
22+
}
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package org.cardanofoundation.lob.app.accounting_reporting_core.config;
2+
3+
import org.springframework.context.annotation.Bean;
4+
import org.springframework.context.annotation.Configuration;
5+
import org.springframework.modulith.events.core.EventSerializer;
6+
7+
@Configuration
8+
public class ModulithEventConfig {
9+
10+
@Bean
11+
public EventSerializer eventSerializer() {
12+
return new EventSerializer() {
13+
@Override
14+
public Object serialize(Object event) {
15+
return null;
16+
}
17+
18+
@Override
19+
public <T> T deserialize(Object serialized, Class<T> type) {
20+
return null;
21+
}
22+
};
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package org.cardanofoundation.lob.app.accounting_reporting_core.config;
2+
3+
import java.time.Clock;
4+
import java.time.Instant;
5+
import java.time.ZoneId;
6+
7+
import lombok.extern.slf4j.Slf4j;
8+
9+
import org.springframework.context.annotation.Bean;
10+
import org.springframework.context.annotation.Configuration;
11+
12+
@Configuration
13+
@Slf4j
14+
public class TimeConfig {
15+
16+
@Bean
17+
public Clock clock() {
18+
// Set the fixed instant and time zone
19+
log.info("Setting fixed clock for testing...");
20+
Instant fixedInstant = Instant.parse("2025-02-26T00:00:00.00Z");
21+
ZoneId zoneId = ZoneId.of("UTC");
22+
return Clock.fixed(fixedInstant, zoneId);
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package org.cardanofoundation.lob.app.accounting_reporting_core.resource;
2+
3+
import static org.mockito.ArgumentMatchers.any;
4+
import static org.mockito.Mockito.verify;
5+
import static org.mockito.Mockito.verifyNoInteractions;
6+
import static org.mockito.Mockito.verifyNoMoreInteractions;
7+
import static org.mockito.Mockito.when;
8+
import static org.zalando.problem.Status.BAD_REQUEST;
9+
10+
import org.springframework.http.ResponseEntity;
11+
12+
import io.vavr.control.Either;
13+
import org.mockito.InjectMocks;
14+
import org.mockito.Mock;
15+
import org.mockito.junit.jupiter.MockitoExtension;
16+
import org.zalando.problem.Problem;
17+
18+
import org.junit.jupiter.api.Assertions;
19+
import org.junit.jupiter.api.Test;
20+
import org.junit.jupiter.api.extension.ExtendWith;
21+
22+
import org.cardanofoundation.lob.app.accounting_reporting_core.resource.presentation_layer_service.AccountingCorePresentationViewService;
23+
import org.cardanofoundation.lob.app.accounting_reporting_core.resource.requests.ReconciliationFilterRequest;
24+
import org.cardanofoundation.lob.app.accounting_reporting_core.resource.requests.ReconciliationRejectionCodeRequest;
25+
import org.cardanofoundation.lob.app.accounting_reporting_core.resource.requests.ReconciliationRequest;
26+
import org.cardanofoundation.lob.app.accounting_reporting_core.service.internal.AccountingCoreService;
27+
28+
@ExtendWith(MockitoExtension.class)
29+
class AccountingCoreResourceReconciliationTest {
30+
31+
@Mock
32+
private AccountingCorePresentationViewService accountingCorePresentationViewService;
33+
@Mock
34+
private AccountingCoreService accountingCoreService;
35+
36+
@InjectMocks
37+
private AccountingCoreResourceReconciliation accountingCoreResourceReconciliation;
38+
39+
@Test
40+
void testReconcileTriggerAction_successfull() {
41+
when(accountingCoreService.scheduleReconcilation(any(), any(), any())).thenReturn(Either.right(null));
42+
ResponseEntity<?> responseEntity = accountingCoreResourceReconciliation.reconcileTriggerAction(new ReconciliationRequest());
43+
Assertions.assertEquals(200, responseEntity.getStatusCode().value());
44+
verify(accountingCoreService).scheduleReconcilation(any(), any(), any());
45+
verifyNoMoreInteractions(accountingCoreService);
46+
verifyNoInteractions(accountingCorePresentationViewService);
47+
}
48+
49+
@Test
50+
void testReconcileTriggerAction_problem() {
51+
when(accountingCoreService.scheduleReconcilation(any(), any(), any())).thenReturn(Either.left(Problem.builder()
52+
.withTitle("title")
53+
.withStatus(BAD_REQUEST)
54+
.build()));
55+
ResponseEntity<?> responseEntity = accountingCoreResourceReconciliation.reconcileTriggerAction(new ReconciliationRequest());
56+
57+
Assertions.assertEquals(400, responseEntity.getStatusCode().value());
58+
verify(accountingCoreService).scheduleReconcilation(any(), any(), any());
59+
verifyNoMoreInteractions(accountingCoreService);
60+
verifyNoInteractions(accountingCorePresentationViewService);
61+
}
62+
63+
@Test
64+
void testReconcileStart() {
65+
when(accountingCorePresentationViewService.allReconciliationTransaction(any())).thenReturn(null);
66+
ResponseEntity<?> responseEntity = accountingCoreResourceReconciliation.reconcileStart(new ReconciliationFilterRequest(), 0, 10);
67+
Assertions.assertEquals(200, responseEntity.getStatusCode().value());
68+
verify(accountingCorePresentationViewService).allReconciliationTransaction(any());
69+
verifyNoMoreInteractions(accountingCorePresentationViewService);
70+
verifyNoInteractions(accountingCoreService);
71+
}
72+
73+
@Test
74+
void testReconciliationRejectionCode() {
75+
ResponseEntity<?> responseEntity = accountingCoreResourceReconciliation.reconciliationRejectionCode();
76+
Assertions.assertEquals(200, responseEntity.getStatusCode().value());
77+
ReconciliationRejectionCodeRequest[] body = (ReconciliationRejectionCodeRequest[])responseEntity.getBody();
78+
Assertions.assertNotNull(body);
79+
Assertions.assertEquals(5, body.length);
80+
verifyNoInteractions(accountingCoreService);
81+
verifyNoInteractions(accountingCorePresentationViewService);
82+
}
83+
}

0 commit comments

Comments
 (0)