Skip to content

Commit 7ecc61a

Browse files
testcontainers
1 parent 99c7dc8 commit 7ecc61a

File tree

7 files changed

+294
-4
lines changed

7 files changed

+294
-4
lines changed

docker-compose-db-only.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
services:
2+
db-local-postgres:
3+
container_name: jfs-postgres-local
4+
image: postgres
5+
environment:
6+
POSTGRES_USER: amigoscode
7+
POSTGRES_PASSWORD: password
8+
POSTGRES_DB: jfs
9+
ports:
10+
- "5333:5432"
11+
restart: unless-stopped
12+
volumes:
13+
- db-local:/data/postgres
14+
networks:
15+
- amigos
16+
17+
networks:
18+
amigos:
19+
driver: bridge
20+
21+
volumes:
22+
db-local:

pom.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,18 @@
6969
<groupId>org.flywaydb</groupId>
7070
<artifactId>flyway-database-postgresql</artifactId>
7171
</dependency>
72+
<dependency>
73+
<groupId>org.testcontainers</groupId>
74+
<artifactId>junit-jupiter</artifactId>
75+
</dependency>
76+
<dependency>
77+
<groupId>org.testcontainers</groupId>
78+
<artifactId>postgresql</artifactId>
79+
</dependency>
80+
<dependency>
81+
<groupId>org.springframework.boot</groupId>
82+
<artifactId>spring-boot-testcontainers</artifactId>
83+
</dependency>
7284
</dependencies>
7385

7486
<build>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
package com.amigoscode.product;
22

33
import org.springframework.data.jpa.repository.JpaRepository;
4+
import org.springframework.data.jpa.repository.Query;
45

6+
import java.util.List;
57
import java.util.UUID;
68

79
public interface ProductRepository
810
extends JpaRepository<Product, UUID> {
11+
12+
@Query("SELECT p FROM Product p WHERE p.isPublished AND p.stockLevel > 0 ORDER BY p.price ASC")
13+
List<Product> findAvailablePublishedProducts();
914
}

src/main/java/com/amigoscode/product/ProductService.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22

33
import com.amigoscode.exception.ResourceNotFound;
44
import org.springframework.stereotype.Service;
5-
import org.springframework.web.bind.annotation.PathVariable;
6-
import org.springframework.web.bind.annotation.PutMapping;
7-
import org.springframework.web.bind.annotation.RequestBody;
85

96
import java.util.List;
107
import java.util.UUID;
@@ -57,7 +54,7 @@ public UUID saveNewProduct(NewProductRequest product) {
5754
return id;
5855
}
5956

60-
private Function<Product, ProductResponse> mapToResponse() {
57+
Function<Product, ProductResponse> mapToResponse() {
6158
return p -> new ProductResponse(
6259
p.getId(),
6360
p.getName(),
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.amigoscode;
2+
3+
import org.flywaydb.core.Flyway;
4+
import org.testcontainers.containers.PostgreSQLContainer;
5+
import org.testcontainers.utility.DockerImageName;
6+
7+
public class SharedPostgresContainer extends PostgreSQLContainer<SharedPostgresContainer> {
8+
private static final DockerImageName IMAGE_NAME
9+
= DockerImageName.parse("postgres:17-alpine");
10+
11+
private static volatile SharedPostgresContainer sharedPostgresContainer;
12+
13+
public SharedPostgresContainer(DockerImageName dockerImageName) {
14+
super(dockerImageName);
15+
this.withReuse(true)
16+
.withUsername("amigoscode")
17+
.withDatabaseName("amigos")
18+
.withLabel("name", "amigscode")
19+
.withPassword("password");
20+
}
21+
22+
public static SharedPostgresContainer getInstance() {
23+
if(sharedPostgresContainer == null) {
24+
synchronized (SharedPostgresContainer.class) {
25+
sharedPostgresContainer = new SharedPostgresContainer(
26+
IMAGE_NAME
27+
);
28+
sharedPostgresContainer.start();
29+
Flyway flyway = Flyway.configure()
30+
.dataSource(
31+
sharedPostgresContainer.getJdbcUrl(),
32+
sharedPostgresContainer.getUsername(),
33+
sharedPostgresContainer.getPassword()
34+
)
35+
.load();
36+
flyway.migrate();
37+
System.out.println("flyway applied migrations");
38+
}
39+
}
40+
return sharedPostgresContainer;
41+
}
42+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package com.amigoscode.product;
2+
3+
import com.amigoscode.SharedPostgresContainer;
4+
import org.junit.jupiter.api.BeforeEach;
5+
import org.junit.jupiter.api.Test;
6+
import org.springframework.beans.factory.annotation.Autowired;
7+
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
8+
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
9+
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
10+
import org.testcontainers.junit.jupiter.Container;
11+
import org.testcontainers.junit.jupiter.Testcontainers;
12+
13+
import java.math.BigDecimal;
14+
import java.util.List;
15+
import java.util.UUID;
16+
17+
import static org.assertj.core.api.Assertions.assertThat;
18+
19+
@DataJpaTest
20+
@AutoConfigureTestDatabase(
21+
replace = AutoConfigureTestDatabase.Replace.NONE
22+
)
23+
@Testcontainers
24+
class ProductRepositoryTest {
25+
26+
@Container
27+
@ServiceConnection
28+
private static final SharedPostgresContainer POSTGRES =
29+
SharedPostgresContainer.getInstance();
30+
31+
32+
@Autowired
33+
private ProductRepository underTest;
34+
35+
@BeforeEach
36+
void setUp() {
37+
underTest.deleteAll();
38+
}
39+
40+
@Test
41+
void canFindAvailablePublishedProducts() {
42+
// given
43+
Product product1 = new Product(
44+
UUID.randomUUID(),
45+
"iphone",
46+
"bardnjknjkndsjknkjnajkndjksandsajkndkjasnkdjank",
47+
new BigDecimal("1000"),
48+
"https://amigoscode.com/logo.png",
49+
10
50+
);
51+
52+
Product product2 = new Product(
53+
UUID.randomUUID(),
54+
"samsung",
55+
"bardnjknjkndsjknkjnajkndjksandsajkndkjasnkdjank",
56+
new BigDecimal("1200"),
57+
"https://amigoscode.com/logo.png",
58+
5
59+
);
60+
product2.setPublished(false);
61+
62+
Product product3 = new Product(
63+
UUID.randomUUID(),
64+
"watch",
65+
"bardnjknjkndsjknkjnajkndjksandsajkndkjasnkdjank",
66+
new BigDecimal("5000"),
67+
"https://amigoscode.com/logo.png",
68+
0
69+
);
70+
71+
Product product4 = new Product(
72+
UUID.randomUUID(),
73+
"PS5",
74+
"bardnjknjkndsjknkjnajkndjksandsajkndkjasnkdjank",
75+
new BigDecimal("300"),
76+
"https://amigoscode.com/logo.png",
77+
90
78+
);
79+
80+
underTest.saveAll(
81+
List.of(product1, product2, product3, product4)
82+
);
83+
// when
84+
List<Product> availablePublishedProducts =
85+
underTest.findAvailablePublishedProducts();
86+
// then
87+
assertThat(availablePublishedProducts)
88+
.usingRecursiveFieldByFieldElementComparatorIgnoringFields(
89+
"updatedAt", "createdAt"
90+
)
91+
.containsExactly(
92+
product4, product1
93+
);
94+
}
95+
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package com.amigoscode.product;
2+
3+
import com.amigoscode.SharedPostgresContainer;
4+
import org.junit.jupiter.api.BeforeAll;
5+
import org.junit.jupiter.api.BeforeEach;
6+
import org.junit.jupiter.api.Disabled;
7+
import org.junit.jupiter.api.Test;
8+
import org.springframework.beans.factory.annotation.Autowired;
9+
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
10+
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
11+
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
12+
import org.springframework.context.annotation.Import;
13+
import org.testcontainers.junit.jupiter.Container;
14+
import org.testcontainers.junit.jupiter.Testcontainers;
15+
16+
import java.math.BigDecimal;
17+
import java.util.List;
18+
import java.util.UUID;
19+
20+
import static org.assertj.core.api.Assertions.assertThat;
21+
22+
@DataJpaTest
23+
@AutoConfigureTestDatabase(
24+
replace = AutoConfigureTestDatabase.Replace.NONE
25+
)
26+
@Import({
27+
ProductService.class
28+
})
29+
@Testcontainers
30+
class ProductServiceTest {
31+
32+
@Container
33+
@ServiceConnection
34+
private static final SharedPostgresContainer POSTGRES =
35+
SharedPostgresContainer.getInstance();
36+
37+
@Autowired
38+
private ProductRepository productRepository;
39+
40+
@Autowired
41+
private ProductService underTest;
42+
43+
@BeforeAll
44+
static void beforeAll() {
45+
System.out.println(POSTGRES.getDatabaseName());
46+
System.out.println(POSTGRES.getJdbcUrl());
47+
System.out.println(POSTGRES.getPassword());
48+
System.out.println(POSTGRES.getDriverClassName());
49+
System.out.println(POSTGRES.getTestQueryString());
50+
}
51+
52+
@BeforeEach
53+
void setUp() {
54+
productRepository.deleteAll();
55+
}
56+
57+
@Test
58+
@Disabled
59+
void canGetAllProducts() {
60+
// given
61+
Product product = new Product(
62+
UUID.randomUUID(),
63+
"foo",
64+
"bardnjknjkndsjknkjnajkndjksandsajkndkjasnkdjank",
65+
BigDecimal.TEN,
66+
"https://amigoscode.com/logo.png",
67+
10
68+
);
69+
70+
productRepository.save(product);
71+
72+
// when
73+
List<ProductResponse> allProducts =
74+
underTest.getAllProducts();
75+
// then
76+
ProductResponse expected = underTest.mapToResponse().apply(product);
77+
78+
assertThat(allProducts)
79+
.usingRecursiveFieldByFieldElementComparatorIgnoringFields(
80+
"updatedAt", "createdAt"
81+
)
82+
.containsOnly(expected);
83+
84+
}
85+
86+
@Test
87+
@Disabled
88+
void getProductById() {
89+
// given
90+
// when
91+
// then
92+
}
93+
94+
@Test
95+
@Disabled
96+
void deleteProductById() {
97+
// given
98+
// when
99+
// then
100+
}
101+
102+
@Test
103+
@Disabled
104+
void saveNewProduct() {
105+
// given
106+
// when
107+
// then
108+
}
109+
110+
@Test
111+
@Disabled
112+
void updateProduct() {
113+
// given
114+
// when
115+
// then
116+
}
117+
}

0 commit comments

Comments
 (0)