Skip to content

Commit ad420d5

Browse files
committed
test: Set up test containers and add the first integration as well as unit tests #9
1 parent 9e3e055 commit ad420d5

8 files changed

Lines changed: 195 additions & 9 deletions

File tree

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
name: 'Backend tests'
2+
3+
on: [push]
4+
jobs:
5+
backend-tests:
6+
runs-on: ubuntu-24.04
7+
env:
8+
TZ: 'Europe/Zurich'
9+
steps:
10+
- name: Checkout
11+
uses: actions/checkout@v5
12+
13+
- name: Set up JDK ${{vars.JAVA_VERSION}}
14+
uses: actions/setup-java@v4
15+
with:
16+
java-version: ${{vars.JAVA_VERSION}}
17+
distribution: 'adopt'
18+
19+
- name: Use Maven to run unittests and integration tests
20+
run: mvn clean verify

backend/pom.xml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,19 @@
6161
<version>2.8.9</version>
6262
</dependency>
6363

64+
<dependency>
65+
<groupId>org.testcontainers</groupId>
66+
<artifactId>junit-jupiter</artifactId>
67+
<version>1.19.8</version>
68+
<scope>test</scope>
69+
</dependency>
70+
<dependency>
71+
<groupId>org.testcontainers</groupId>
72+
<artifactId>postgresql</artifactId>
73+
<version>1.19.8</version>
74+
<scope>test</scope>
75+
</dependency>
76+
6477
<!-- Dev Tools -->
6578
<dependency>
6679
<groupId>org.springframework.boot</groupId>
@@ -85,6 +98,16 @@
8598
<artifactId>spring-security-test</artifactId>
8699
<scope>test</scope>
87100
</dependency>
101+
<dependency>
102+
<groupId>junit</groupId>
103+
<artifactId>junit</artifactId>
104+
<version>4.13.2</version>
105+
</dependency>
106+
<dependency>
107+
<groupId>junit</groupId>
108+
<artifactId>junit</artifactId>
109+
<scope>test</scope>
110+
</dependency>
88111
</dependencies>
89112
<build>
90113
<plugins>
@@ -127,6 +150,11 @@
127150
</java>
128151
</configuration>
129152
</plugin>
153+
<plugin>
154+
<groupId>org.apache.maven.plugins</groupId>
155+
<artifactId>maven-surefire-plugin</artifactId>
156+
<version>3.5.3</version>
157+
</plugin>
130158
</plugins>
131159
</build>
132160

backend/src/main/java/ch/puzzle/pcts/controller/ExampleController.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import ch.puzzle.pcts.dto.example.ExampleDto;
44
import ch.puzzle.pcts.mapper.ExampleMapper;
55
import ch.puzzle.pcts.model.example.Example;
6-
import ch.puzzle.pcts.service.business.ExampleService;
6+
import ch.puzzle.pcts.service.business.ExampleBusinessService;
77
import io.swagger.v3.oas.annotations.Operation;
88
import io.swagger.v3.oas.annotations.media.Content;
99
import io.swagger.v3.oas.annotations.media.Schema;
@@ -24,10 +24,10 @@
2424
@RequestMapping("/api/v1/examples")
2525
public class ExampleController {
2626
private final ExampleMapper mapper;
27-
private final ExampleService service;
27+
private final ExampleBusinessService service;
2828

2929
@Autowired
30-
public ExampleController(ExampleMapper mapper, ExampleService service) {
30+
public ExampleController(ExampleMapper mapper, ExampleBusinessService service) {
3131
this.mapper = mapper;
3232
this.service = service;
3333
}

backend/src/main/java/ch/puzzle/pcts/service/business/ExampleService.java renamed to backend/src/main/java/ch/puzzle/pcts/service/business/ExampleBusinessService.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@
88
import org.springframework.stereotype.Service;
99

1010
@Service
11-
public class ExampleService {
11+
public class ExampleBusinessService {
1212
private final ExampleValidationService validationService;
1313
private final ExamplePersistenceService persistenceService;
1414

15-
public ExampleService(ExampleValidationService validationService, ExamplePersistenceService persistenceService) {
15+
public ExampleBusinessService(ExampleValidationService validationService,
16+
ExamplePersistenceService persistenceService) {
1617
this.validationService = validationService;
1718
this.persistenceService = persistenceService;
1819
}

backend/src/main/resources/db/test-data-migration/V0_0_2__initialData.sql

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@ TRUNCATE TABLE example CASCADE;
33

44
INSERT INTO example (id, text)
55
VALUES (1, 'Example 1'),
6-
(2, 'Example 2'),
7-
(3, 'Example 3'),
8-
(4, 'Example 4'),
9-
(5, 'Example 5');
6+
(2, 'Example 2');
107

118
SELECT setval('sequence_example', (SELECT MAX(id) FROM example));
129

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package ch.puzzle.pcts.controller;
2+
3+
import ch.puzzle.pcts.mapper.ExampleMapper;
4+
import ch.puzzle.pcts.service.business.ExampleBusinessService;
5+
import org.junit.jupiter.api.BeforeEach;
6+
import org.mockito.InjectMocks;
7+
import org.mockito.Mock;
8+
import org.mockito.MockitoAnnotations;
9+
10+
class ExampleControllerTest {
11+
12+
@Mock
13+
private ExampleMapper mapper;
14+
15+
@Mock
16+
private ExampleBusinessService service;
17+
18+
@InjectMocks
19+
private ExampleController controller;
20+
21+
@BeforeEach
22+
void setup() {
23+
MockitoAnnotations.openMocks(this);
24+
}
25+
26+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package ch.puzzle.pcts.service.business;
2+
3+
import static org.junit.jupiter.api.Assertions.*;
4+
import static org.mockito.Mockito.*;
5+
6+
import ch.puzzle.pcts.model.example.Example;
7+
import ch.puzzle.pcts.service.persistence.ExamplePersistenceService;
8+
import ch.puzzle.pcts.service.validation.ExampleValidationService;
9+
import java.util.List;
10+
import org.junit.jupiter.api.BeforeEach;
11+
import org.junit.jupiter.api.Test;
12+
import org.mockito.InjectMocks;
13+
import org.mockito.Mock;
14+
import org.mockito.MockitoAnnotations;
15+
16+
class ExampleBusinessServiceTest {
17+
18+
@Mock
19+
private ExampleValidationService validationService;
20+
21+
@Mock
22+
private ExamplePersistenceService persistenceService;
23+
24+
@InjectMocks
25+
private ExampleBusinessService businessService;
26+
27+
@BeforeEach
28+
void setUp() {
29+
MockitoAnnotations.openMocks(this);
30+
}
31+
32+
@Test
33+
void testGetById() {
34+
Example example = new Example(1L, "Example1");
35+
when(persistenceService.getById(1L)).thenReturn(example);
36+
37+
Example result = businessService.getById(1L);
38+
39+
assertEquals(example, result);
40+
verify(persistenceService).getById(1L);
41+
}
42+
43+
@Test
44+
void testGetAll() {
45+
List<Example> examples = List.of(new Example(1L, "Example1"), new Example(2L, "Example2"));
46+
when(persistenceService.getAll()).thenReturn(examples);
47+
48+
List<Example> result = businessService.getAll();
49+
50+
assertEquals(2, result.size());
51+
verify(persistenceService).getAll();
52+
}
53+
54+
@Test
55+
void testCreate() {
56+
Example example = new Example(1L, "Example1");
57+
when(persistenceService.create(example)).thenReturn(example);
58+
59+
Example result = businessService.create(example);
60+
61+
assertEquals(example, result);
62+
verify(validationService).validateOnCreate(example);
63+
verify(persistenceService).create(example);
64+
}
65+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package ch.puzzle.pcts.service.persistence;
2+
3+
import static org.assertj.core.api.Assertions.assertThat;
4+
5+
import ch.puzzle.pcts.model.example.Example;
6+
import java.util.List;
7+
import org.junit.jupiter.api.Test;
8+
import org.springframework.beans.factory.annotation.Autowired;
9+
import org.springframework.boot.test.context.SpringBootTest;
10+
import org.springframework.test.context.ActiveProfiles;
11+
import org.springframework.test.context.DynamicPropertyRegistry;
12+
import org.springframework.test.context.DynamicPropertySource;
13+
import org.testcontainers.containers.PostgreSQLContainer;
14+
import org.testcontainers.junit.jupiter.Container;
15+
import org.testcontainers.junit.jupiter.Testcontainers;
16+
17+
@SpringBootTest
18+
@Testcontainers
19+
@ActiveProfiles("test")
20+
class ExamplePersistenceServiceIT {
21+
22+
@Container
23+
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16-alpine");
24+
25+
@DynamicPropertySource
26+
static void configureProperties(DynamicPropertyRegistry registry) {
27+
registry.add("spring.datasource.url", postgres::getJdbcUrl);
28+
registry.add("spring.datasource.username", postgres::getUsername);
29+
registry.add("spring.datasource.password", postgres::getPassword);
30+
}
31+
32+
@Autowired
33+
private ExamplePersistenceService persistenceService;
34+
35+
@Test
36+
void connectionEstablished() {
37+
assertThat(postgres.isRunning()).isTrue();
38+
}
39+
40+
@Test
41+
void testGetAll() {
42+
// when
43+
List<Example> all = persistenceService.getAll();
44+
45+
// then
46+
assertThat(all).hasSize(2);
47+
assertThat(all).extracting(Example::getText).containsExactlyInAnyOrder("Example 1", "Example 2");
48+
}
49+
}

0 commit comments

Comments
 (0)