Skip to content

Commit 6de4f66

Browse files
committed
Enhance ProfileImportIT test and clean up unnecessary code
Updated the ProfileImportIT test case by adding budget verification and enabling the import of user profiles with budgets. Removed unused mock settings from ProcessTestExtension and added budget-related mock settings in RuntimeContext. These changes provide a more comprehensive test coverage and a cleaner codebase.
1 parent 09b2392 commit 6de4f66

File tree

3 files changed

+105
-23
lines changed

3 files changed

+105
-23
lines changed

bpmn-process/src/test/java/com/jongsoft/finance/bpmn/ProfileImportIT.java

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.jongsoft.finance.bpmn.process.RuntimeContext;
55
import com.jongsoft.finance.core.RuleColumn;
66
import com.jongsoft.finance.domain.account.Account;
7+
import com.jongsoft.finance.domain.user.Budget;
78
import com.jongsoft.lang.collection.Sequence;
89
import org.assertj.core.api.Assertions;
910
import org.junit.jupiter.api.DisplayName;
@@ -100,7 +101,8 @@ void runWithTags(RuntimeContext context) {
100101

101102
context
102103
.verifyTagCreated("cat")
103-
.verifyTagCreated("dog");
104+
.verifyTagCreated("dog")
105+
.verifyTagCreated("charity");
104106
}
105107

106108
@Test
@@ -166,15 +168,31 @@ void runWithTransactions(RuntimeContext context) {
166168
}));
167169
}
168170

169-
// @Test
170-
// @DisplayName("Import a profile with budgets")
171-
// void runWithBudgets(RuntimeContext context) {
172-
// context
173-
// .withStorage()
174-
// .withStorage("my-sample-token", "/profile-test/budget-only.json");
175-
//
176-
// context.execute("ImportUserProfile", Map.of(
177-
// "storageToken", "my-sample-token"))
178-
// .verifyCompleted();
179-
// }
171+
@Test
172+
@DisplayName("Import a profile with budgets")
173+
@SuppressWarnings("unchecked")
174+
void runWithBudgets(RuntimeContext context) {
175+
context
176+
.withBudgets()
177+
.withStorage()
178+
.withStorage("my-sample-token", "/profile-test/budget-only.json");
179+
context.execute("ImportUserProfile", Map.of(
180+
"storageToken", "my-sample-token"))
181+
.verifyCompleted();
182+
183+
context.verifyBudget(LocalDate.parse("2011-12-01"), budget -> {
184+
budget.extracting("expectedIncome", "start")
185+
.containsExactlyInAnyOrder(2500D, LocalDate.parse("2011-12-01"));
186+
187+
budget.extracting("expenses")
188+
.satisfies(expenses -> {
189+
Assertions.assertThat((Sequence<Budget.Expense>) expenses)
190+
.extracting(Budget.Expense::getName)
191+
.containsExactlyInAnyOrder("Sparen", "Vervoer", "Abonnementen", "Huishoudelijke kosten", "Boodschappen");
192+
});
193+
});
194+
context.verifyBudget(LocalDate.parse("2012-12-01"), budget ->
195+
budget.extracting("expectedIncome", "start")
196+
.containsExactlyInAnyOrder(3000D, LocalDate.parse("2012-12-01")));
197+
}
180198
}

bpmn-process/src/test/java/com/jongsoft/finance/bpmn/process/ProcessTestExtension.java

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,18 @@
11
package com.jongsoft.finance.bpmn.process;
22

3-
import com.jongsoft.finance.messaging.EventBus;
43
import io.micronaut.context.annotation.Property;
5-
import io.micronaut.context.event.ApplicationEventPublisher;
64
import io.micronaut.core.annotation.Nullable;
75
import io.micronaut.test.extensions.junit5.MicronautJunit5Extension;
86
import org.junit.jupiter.api.extension.ExtensionContext;
97
import org.junit.jupiter.api.extension.ParameterContext;
108
import org.junit.jupiter.api.extension.ParameterResolutionException;
11-
import org.mockito.Mockito;
129

1310
import java.lang.reflect.AnnotatedElement;
1411
import java.util.List;
1512
import java.util.function.Consumer;
1613

1714
public class ProcessTestExtension extends MicronautJunit5Extension {
1815

19-
static {
20-
new EventBus(Mockito.mock(ApplicationEventPublisher.class));
21-
}
22-
2316
public interface ProcessExecution<T extends ProcessExecution> {
2417
ProcessExecution<?> obtainChildProcess(String processKey);
2518
T verifyCompleted();

bpmn-process/src/test/java/com/jongsoft/finance/bpmn/process/RuntimeContext.java

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
import com.jongsoft.finance.domain.user.Role;
1616
import com.jongsoft.finance.domain.user.UserAccount;
1717
import com.jongsoft.finance.factory.FilterFactory;
18+
import com.jongsoft.finance.messaging.EventBus;
19+
import com.jongsoft.finance.messaging.commands.budget.CreateBudgetCommand;
1820
import com.jongsoft.finance.messaging.commands.transaction.CreateTransactionCommand;
1921
import com.jongsoft.finance.messaging.handlers.TransactionCreationHandler;
2022
import com.jongsoft.finance.providers.*;
@@ -24,6 +26,7 @@
2426
import com.jongsoft.lang.Control;
2527
import com.jongsoft.lang.control.Optional;
2628
import io.micronaut.context.ApplicationContext;
29+
import io.micronaut.context.event.ApplicationEventPublisher;
2730
import io.micronaut.core.reflect.ReflectionUtils;
2831
import lombok.extern.slf4j.Slf4j;
2932
import org.apache.commons.lang3.mutable.MutableLong;
@@ -36,23 +39,23 @@
3639
import org.mockito.stubbing.OngoingStubbing;
3740

3841
import java.math.BigDecimal;
39-
import java.util.ArrayList;
40-
import java.util.List;
41-
import java.util.Map;
42-
import java.util.UUID;
42+
import java.time.LocalDate;
43+
import java.util.*;
4344
import java.util.function.Consumer;
4445

4546
@Slf4j
4647
public class RuntimeContext {
4748

4849
private ApplicationContext applicationContext;
50+
private ApplicationEventPublisher applicationEventPublisher;
4951

5052
private ProcessEngine processEngine;
5153

5254
private UserAccount userAccount;
5355

5456
private final List<String> storageTokens;
5557
private final MutableLong idGenerator;
58+
private final List<Budget> registeredBudgets;
5659

5760
public RuntimeContext(ApplicationContext applicationContext) {
5861
this.applicationContext = applicationContext;
@@ -64,14 +67,17 @@ public RuntimeContext(ApplicationContext applicationContext) {
6467
.roles(Collections.List(new Role("admin")))
6568
.build());
6669
this.processEngine = applicationContext.getBean(ProcessEngine.class);
70+
this.applicationEventPublisher = Mockito.spy(applicationContext.getBean(ApplicationEventPublisher.class));
6771
idGenerator = new MutableLong(100);
72+
registeredBudgets = new ArrayList<>();
6873

6974
setupDefaultMocks();
7075
}
7176

7277
void clean() {
7378
processEngine.close();
7479
storageTokens.clear();
80+
registeredBudgets.clear();
7581
}
7682

7783
public RuntimeContext withStorage() {
@@ -98,6 +104,34 @@ public RuntimeContext withStorage(String token, String resource) {
98104
return this;
99105
}
100106

107+
@SuppressWarnings("unchecked")
108+
public RuntimeContext withBudgets() {
109+
var budgetProvider = applicationContext.getBean(BudgetProvider.class);
110+
Mockito.when(budgetProvider.lookup(Mockito.anyInt(), Mockito.anyInt()))
111+
.thenAnswer(invocation -> {
112+
var date = LocalDate.of(invocation.getArgument(0), invocation.getArgument(1, Integer.class), 1);
113+
114+
return Control.Option(registeredBudgets.stream()
115+
.filter(budget -> budget.getStart().isBefore(date) || budget.getStart().isEqual(date))
116+
.max(Comparator.comparing(Budget::getStart))
117+
.orElse(null));
118+
});
119+
120+
Mockito.doAnswer((Answer<Void>) invocation -> {
121+
var createCommand = invocation.getArgument(0, CreateBudgetCommand.class);
122+
123+
var budget = Budget.builder()
124+
.start(createCommand.budget().getStart())
125+
.expectedIncome(createCommand.budget().getExpectedIncome())
126+
.id(idGenerator.getAndIncrement())
127+
.expenses(Collections.List())
128+
.build();
129+
registeredBudgets.add(budget);
130+
return null;
131+
}).when(applicationEventPublisher).publishEvent(Mockito.any(CreateBudgetCommand.class));
132+
return this;
133+
}
134+
101135
public RuntimeContext withBudget(int year, int month, Budget budget) {
102136
var budgetProvider = applicationContext.getBean(BudgetProvider.class);
103137
Mockito.when(budgetProvider.lookup(year, month))
@@ -232,12 +266,24 @@ public RuntimeContext verifyAccountCreated(String name, String currency, String
232266
return this;
233267
}
234268

269+
/**
270+
* Verifies if a category with the specified name has been created.
271+
*
272+
* @param name the name of the category to be verified
273+
* @return the current RuntimeContext instance
274+
*/
235275
public RuntimeContext verifyCategoryCreated(String name) {
236276
Mockito.verify(userAccount, Mockito.atMostOnce())
237277
.createCategory(name);
238278
return this;
239279
}
240280

281+
/**
282+
* Verifies the transactions by performing validations provided by the consumer.
283+
*
284+
* @param validations the consumer that accepts a ListAssert<Transaction> for performing validations
285+
* @return the RuntimeContext instance
286+
*/
241287
public RuntimeContext verifyTransactions(Consumer<ListAssert<Transaction>> validations) {
242288
var createdTransactions = Mockito.mockingDetails(applicationContext.getBean(TransactionCreationHandler.class)).getInvocations().stream()
243289
.filter(invocation -> invocation.getMethod().getName().equals("handleCreatedEvent"))
@@ -250,12 +296,34 @@ public RuntimeContext verifyTransactions(Consumer<ListAssert<Transaction>> valid
250296
return this;
251297
}
252298

299+
/**
300+
* Verifies that all storage tokens have been cleaned.
301+
*
302+
* @return The RuntimeContext object.
303+
*/
253304
public RuntimeContext verifyStorageCleaned() {
254305
storageTokens.forEach(token ->
255306
Mockito.verify(applicationContext.getBean(StorageService.class)).remove(token));
256307
return this;
257308
}
258309

310+
/**
311+
* Verifies the budget for the specified start date.
312+
*
313+
* @param startDate the start date of the budget to verify
314+
* @param validations the consumer function that performs assertions on the budget
315+
* @return the current RuntimeContext object
316+
*/
317+
public RuntimeContext verifyBudget(LocalDate startDate, Consumer<ObjectAssert<Budget>> validations) {
318+
validations.accept(
319+
Assertions.assertThat(registeredBudgets.stream()
320+
.filter(budget -> budget.getStart().equals(startDate))
321+
.findFirst()
322+
.orElseThrow(() -> new AssertionError("Budget not found for start date: " + startDate)))
323+
.as("Budget created for start date: " + startDate));
324+
return this;
325+
}
326+
259327
public RuntimeContext verifyRuleCreated(String name, Consumer<ObjectAssert<TransactionRule>> validations) {
260328
var matchedRule = Mockito.mockingDetails(applicationContext.getBean(TransactionRuleProvider.class))
261329
.getInvocations().stream()
@@ -282,6 +350,7 @@ public <T> T verifyInteraction(Class<T> type) {
282350

283351
void resetMocks() {
284352
Mockito.reset(
353+
applicationContext.getBean(BudgetProvider.class),
285354
applicationContext.getBean(AuthenticationFacade.class),
286355
applicationContext.getBean(CurrentUserProvider.class),
287356
applicationContext.getBean(AccountProvider.class),
@@ -303,6 +372,8 @@ private void setupDefaultMocks() {
303372
Mockito.when(applicationContext.getBean(CurrentUserProvider.class).currentUser())
304373
.thenReturn(userAccount);
305374

375+
new EventBus(applicationEventPublisher);
376+
306377
// Prepare the mocks for the filter factory
307378
var filterFactory = applicationContext.getBean(FilterFactory.class);
308379
Mockito.when(filterFactory.account()).thenReturn(Mockito.mock(AccountProvider.FilterCommand.class, Mockito.RETURNS_DEEP_STUBS));

0 commit comments

Comments
 (0)