Skip to content

Commit 0db29af

Browse files
author
yevhenii.nadtochii
committed
Implement tests
1 parent 268ad64 commit 0db29af

File tree

6 files changed

+185
-20
lines changed

6 files changed

+185
-20
lines changed

server/src/test/java/io/spine/server/aggregate/AggregateTest.java

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import io.spine.server.aggregate.given.aggregate.TaskAggregateRepository;
4949
import io.spine.server.aggregate.given.aggregate.TestAggregate;
5050
import io.spine.server.aggregate.given.aggregate.TestAggregateRepository;
51+
import io.spine.server.aggregate.given.salary.EmployeeAgg;
5152
import io.spine.server.aggregate.given.thermometer.SafeThermometer;
5253
import io.spine.server.aggregate.given.thermometer.SafeThermometerRepo;
5354
import io.spine.server.aggregate.given.thermometer.Thermometer;
@@ -79,6 +80,7 @@
7980
import io.spine.test.aggregate.event.AggUserNotified;
8081
import io.spine.test.aggregate.rejection.Rejections.AggCannotReassignUnassignedTask;
8182
import io.spine.testing.logging.mute.MuteLogging;
83+
import io.spine.testing.server.blackbox.BlackBox;
8284
import io.spine.testing.server.blackbox.ContextAwareTest;
8385
import io.spine.testing.server.model.ModelTests;
8486
import io.spine.time.testing.BackToTheFuture;
@@ -111,6 +113,9 @@
111113
import static io.spine.server.aggregate.given.aggregate.AggregateTestEnv.newTenantId;
112114
import static io.spine.server.aggregate.given.aggregate.AggregateTestEnv.reassignTask;
113115
import static io.spine.server.aggregate.given.dispatch.AggregateMessageDispatcher.dispatchCommand;
116+
import static io.spine.server.aggregate.given.salary.Employees.employ;
117+
import static io.spine.server.aggregate.given.salary.Employees.newEmployee;
118+
import static io.spine.server.aggregate.given.salary.Employees.shakeUpSalary;
114119
import static io.spine.server.aggregate.model.AggregateClass.asAggregateClass;
115120
import static io.spine.server.tenant.TenantAwareRunner.with;
116121
import static io.spine.testing.server.Assertions.assertCommandClasses;
@@ -444,13 +449,54 @@ void restoreSnapshot() {
444449
assertEquals(aggregate, anotherAggregate);
445450
}
446451

452+
@Test
453+
@DisplayName("add events to `UncommittedHistory` only if they were successfully applied")
454+
void addEventsToUncommittedOnlyIfApplied() {
455+
var jack = newEmployee();
456+
var employeeAgg = new EmployeeAgg(jack);
457+
458+
employeeAgg.dispatchCommands(
459+
employ(jack, 215),
460+
shakeUpSalary(jack)
461+
);
462+
463+
Aggregate<?, ?, ?> aggregate = employeeAgg;
464+
var uncommitted = aggregate.getUncommittedEvents().list();
465+
assertThat(uncommitted.size()).isEqualTo(1);
466+
}
467+
468+
@Test
469+
@DisplayName("add events to `UncommittedHistory` only if they were successfully applied")
470+
void addEventsToUncommittedOnlyIfApplied2() {
471+
var repository = new DefaultAggregateRepository<>(EmployeeAgg.class);
472+
var context = BlackBox.from(
473+
BoundedContextBuilder.assumingTests()
474+
.add(repository)
475+
);
476+
repository.aggregateStorage().enableStateQuerying();
477+
478+
var jack = newEmployee();
479+
context.tolerateFailures()
480+
.receivesCommands(
481+
employ(jack, 2150),
482+
shakeUpSalary(jack)
483+
);
484+
485+
var storedEvents = repository.aggregateStorage()
486+
.read(jack)
487+
.orElseThrow()
488+
.getEventList();
489+
490+
assertThat(storedEvents.size()).isEqualTo(1);
491+
}
492+
447493
@Nested
448494
@DisplayName("after dispatch, return event records")
449495
class ReturnEventRecords {
450496

451497
@Test
452498
@DisplayName("which are uncommitted")
453-
void uncommitedAfterDispatch() {
499+
void uncommittedAfterDispatch() {
454500
aggregate.dispatchCommands(command(createProject),
455501
command(addTask),
456502
command(startProject));
@@ -493,7 +539,7 @@ class NotHaveEventRecords {
493539

494540
@Test
495541
@DisplayName("which are uncommitted")
496-
void uncommitedByDefault() {
542+
void uncommittedByDefault() {
497543
var events = aggregate().getUncommittedEvents();
498544

499545
assertFalse(events.nonEmpty());

server/src/test/java/io/spine/server/aggregate/given/salary/EmployeeAgg.java

Lines changed: 71 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,43 +25,100 @@
2525
*/
2626
package io.spine.server.aggregate.given.salary;
2727

28+
import io.spine.base.CommandMessage;
29+
import io.spine.base.EventMessage;
30+
import io.spine.server.BoundedContextBuilder;
2831
import io.spine.server.aggregate.Aggregate;
2932
import io.spine.server.aggregate.Apply;
30-
import io.spine.server.aggregate.given.command.DecreaseSalary;
31-
import io.spine.server.aggregate.given.command.IncreaseSalary;
33+
import io.spine.server.aggregate.DefaultAggregateRepository;
34+
import io.spine.server.aggregate.given.command.Employ;
35+
import io.spine.server.aggregate.given.command.ShakeUpSalary;
36+
import io.spine.server.aggregate.given.dispatch.AggregateMessageDispatcher;
37+
import io.spine.server.aggregate.given.salary.event.NewEmployed;
3238
import io.spine.server.aggregate.given.salary.event.SalaryDecreased;
3339
import io.spine.server.aggregate.given.salary.event.SalaryIncreased;
3440
import io.spine.server.command.Assign;
41+
import io.spine.testing.server.blackbox.BlackBox;
42+
import org.junit.jupiter.api.DisplayName;
43+
import org.junit.jupiter.api.Test;
44+
45+
import java.util.List;
46+
47+
import static com.google.common.truth.Truth.assertThat;
48+
import static io.spine.server.aggregate.given.aggregate.AggregateTestEnv.env;
49+
import static io.spine.server.aggregate.given.salary.Employees.employ;
50+
import static io.spine.server.aggregate.given.salary.Employees.newEmployee;
51+
import static io.spine.server.aggregate.given.salary.Employees.shakeUpSalary;
3552

3653
public class EmployeeAgg extends Aggregate<EmployeeId, Employee, Employee.Builder> {
3754

55+
public EmployeeAgg(EmployeeId id) {
56+
super(id);
57+
}
58+
3859
@Assign
39-
SalaryIncreased handle(IncreaseSalary cmd) {
40-
return SalaryIncreased.newBuilder()
60+
NewEmployed handle(Employ cmd) {
61+
return NewEmployed.newBuilder()
4162
.setEmployee(cmd.getEmployee())
42-
.setAmount(cmd.getAmount())
63+
.setSalary(cmd.getSalary())
4364
.vBuild();
4465
}
4566

4667
@Apply
47-
void on(SalaryIncreased event) {
68+
private void on(NewEmployed event) {
4869
builder()
4970
.setId(event.getEmployee())
50-
.setSalary(state().getSalary() + event.getAmount());
71+
.setSalary(event.getSalary());
5172
}
5273

53-
@Assign
54-
SalaryDecreased handle(DecreaseSalary cmd) {
55-
return SalaryDecreased.newBuilder()
56-
.setEmployee(cmd.getEmployee())
57-
.setAmount(cmd.getAmount())
58-
.vBuild();
74+
@Apply
75+
private void on(SalaryIncreased event) {
76+
builder()
77+
.setId(event.getEmployee())
78+
.setSalary(state().getSalary() + event.getAmount());
5979
}
6080

6181
@Apply
62-
void on(SalaryDecreased event) {
82+
private void on(SalaryDecreased event) {
6383
builder()
6484
.setId(event.getEmployee())
6585
.setSalary(state().getSalary() - event.getAmount());
6686
}
87+
88+
@Assign
89+
Iterable<EventMessage> handle(ShakeUpSalary cmd) {
90+
var employee = cmd.getEmployee();
91+
return List.of(
92+
93+
// we need several events to make them processed as a batch.
94+
salaryDecreased(employee, 15),
95+
salaryIncreased(employee, 50),
96+
salaryIncreased(employee, 75),
97+
salaryIncreased(employee, 100),
98+
99+
// this one would make the aggregate's state invalid.
100+
// employee's can not be paid less than 200.
101+
salaryDecreased(employee, 1000)
102+
);
103+
}
104+
105+
private static SalaryIncreased salaryIncreased(EmployeeId employee, int amount) {
106+
return SalaryIncreased.newBuilder()
107+
.setEmployee(employee)
108+
.setAmount(amount)
109+
.vBuild();
110+
}
111+
112+
private static SalaryDecreased salaryDecreased(EmployeeId employee, int amount) {
113+
return SalaryDecreased.newBuilder()
114+
.setEmployee(employee)
115+
.setAmount(amount)
116+
.vBuild();
117+
}
118+
119+
public void dispatchCommands(CommandMessage... commands) {
120+
for (var cmd : commands) {
121+
AggregateMessageDispatcher.dispatchCommand(this, env(cmd));
122+
}
123+
}
67124
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright 2022, TeamDev. All rights reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Redistribution and use in source and/or binary forms, with or without
11+
* modification, must retain the above copyright notice and the following
12+
* disclaimer.
13+
*
14+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17+
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
18+
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
20+
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25+
*/
26+
27+
package io.spine.server.aggregate.given.salary;
28+
29+
import io.spine.server.aggregate.given.command.Employ;
30+
import io.spine.server.aggregate.given.command.ShakeUpSalary;
31+
32+
public class Employees {
33+
34+
private Employees() {
35+
}
36+
37+
public static EmployeeId newEmployee() {
38+
return EmployeeId.generate();
39+
}
40+
41+
public static Employ employ(EmployeeId employee, int salary) {
42+
return Employ.newBuilder()
43+
.setEmployee(employee)
44+
.setSalary(salary)
45+
.vBuild();
46+
}
47+
48+
public static ShakeUpSalary shakeUpSalary(EmployeeId employee) {
49+
return ShakeUpSalary.newBuilder()
50+
.setEmployee(employee)
51+
.vBuild();
52+
}
53+
}

server/src/test/proto/spine/test/aggregate/salary/commands.proto

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,14 @@ option java_multiple_files = true;
3535

3636
import "spine/test/aggregate/salary/employee.proto";
3737

38-
message IncreaseSalary {
38+
message Employ {
3939
EmployeeId employee = 1 [(required) = true];
40-
int32 amount = 2 [(required) = true];
40+
int32 salary = 2 [(required) = true];
4141
}
4242

43-
message DecreaseSalary {
43+
// Triggers multiple modifications (increases\decreases) of an employee's salary.
44+
//
45+
// Used to reach an invalid state of the aggregate in tests.
46+
message ShakeUpSalary {
4447
EmployeeId employee = 1 [(required) = true];
45-
int32 amount = 2 [(required) = true];
4648
}

server/src/test/proto/spine/test/aggregate/salary/employee.proto

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ message Employee {
4343

4444
EmployeeId id = 1 [(required) = true];
4545

46+
// Employee's remuneration for their work.
47+
//
4648
// Let's take 200$ as the lowest remuneration
4749
// which employers can legally pay their employees.
4850
double salary = 2 [(min).value = "200"];

server/src/test/proto/spine/test/aggregate/salary/events.proto

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ option java_multiple_files = true;
3535

3636
import "spine/test/aggregate/salary/employee.proto";
3737

38+
message NewEmployed {
39+
EmployeeId employee = 1 [(required) = true];
40+
int32 salary = 2 [(required) = true];
41+
}
42+
3843
message SalaryIncreased {
3944
EmployeeId employee = 1 [(required) = true];
4045
int32 amount = 2 [(required) = true];

0 commit comments

Comments
 (0)