Skip to content

Commit 5bc10d9

Browse files
author
Guilherme Biff Zarelli
committed
feat: implemented protocol
find protocol in external service and implemented wiremock in acceptance test
1 parent 9771cac commit 5bc10d9

File tree

25 files changed

+498
-46
lines changed

25 files changed

+498
-46
lines changed

acceptance-test/pom.xml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,11 @@
1717
<mutation.skip>true</mutation.skip>
1818
<maven-resources-plugin.version>3.1.0</maven-resources-plugin.version>
1919
<maven-failsafe-plugin.version>2.22.0</maven-failsafe-plugin.version>
20-
<mysql-connector-java.version>8.0.23</mysql-connector-java.version>
20+
<mysql-connector-java.version>8.0.25</mysql-connector-java.version>
2121
<docker-maven-plugin.version>0.35.0</docker-maven-plugin.version>
2222
<run-java-sh.version>1.2.2</run-java-sh.version>
2323
<mutation.skip>true</mutation.skip>
24+
<wiremock-jre8.version>2.27.2</wiremock-jre8.version>
2425
</properties>
2526

2627
<dependencies>
@@ -92,6 +93,12 @@
9293
<artifactId>javafaker</artifactId>
9394
<scope>test</scope>
9495
</dependency>
96+
<dependency>
97+
<groupId>com.github.tomakehurst</groupId>
98+
<artifactId>wiremock-jre8</artifactId>
99+
<version>${wiremock-jre8.version}</version>
100+
<scope>test</scope>
101+
</dependency>
95102
</dependencies>
96103

97104

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,83 @@
11
package br.com.helpdev.atdd;
22

3+
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
4+
5+
import com.github.tomakehurst.wiremock.WireMockServer;
36
import io.restassured.RestAssured;
47
import org.slf4j.LoggerFactory;
8+
import org.testcontainers.Testcontainers;
59
import org.testcontainers.containers.GenericContainer;
610
import org.testcontainers.containers.MySQLContainer;
711
import org.testcontainers.containers.Network;
812
import org.testcontainers.containers.output.Slf4jLogConsumer;
913
import org.testcontainers.containers.wait.strategy.Wait;
14+
import org.testcontainers.lifecycle.Startable;
1015
import org.testcontainers.utility.MountableFile;
1116

1217
abstract class AbstractContainerBaseTest {
1318

1419
private static final GenericContainer<?> APP;
1520
private static final GenericContainer<?> FLYWAY;
16-
private static final GenericContainer<?> MY_SQL_CONTAINER;
21+
private static final GenericContainer<?> MYSQL_CONTAINER;
22+
protected static final WireMockServer MOCK_SERVER;
1723

1824
static {
1925
final var network = Network.newNetwork();
2026

21-
MY_SQL_CONTAINER = new MySQLContainer<>("mysql:5.7.22")
27+
MOCK_SERVER = new WireMockServer(wireMockConfig().dynamicPort());
28+
MOCK_SERVER.start();
29+
exposeHostMachinePortToContainersForApiIntegrations();
30+
31+
MYSQL_CONTAINER = buildMySqlContainer(network);
32+
MYSQL_CONTAINER.start();
33+
34+
FLYWAY = buildFlywayContainer(network, MYSQL_CONTAINER);
35+
FLYWAY.start();
36+
37+
APP = buildAppContainer(network, MYSQL_CONTAINER, FLYWAY);
38+
APP.start();
39+
40+
initRestAssured();
41+
}
42+
43+
private static GenericContainer<?> buildMySqlContainer(final Network network) {
44+
return new MySQLContainer<>("mysql:5.7.22")
2245
.withNetwork(network)
2346
.withNetworkAliases("testdb");
47+
}
2448

25-
FLYWAY = new GenericContainer<>("flyway/flyway")
26-
.dependsOn(MY_SQL_CONTAINER)
49+
private static GenericContainer<?> buildFlywayContainer(final Network network, final Startable... dependsOn) {
50+
return new GenericContainer<>("flyway/flyway")
51+
.dependsOn(dependsOn)
2752
.withNetwork(network)
2853
.withCopyFileToContainer(MountableFile.forHostPath("../resources/flyway/db"), "/flyway/sql")
2954
.withCommand("-url=jdbc:mysql://testdb?useSSL=false -schemas=test -user=test -password=test -connectRetries=60 migrate")
3055
.waitingFor(Wait.forLogMessage("(?s).*No migration necessary(?s).*|(?s).*Successfully applied(?s).*", 1))
3156
.withLogConsumer(new Slf4jLogConsumer(LoggerFactory.getLogger("FLYWAY")));
57+
}
3258

33-
APP = new GenericContainer<>("app-test:integration")
34-
.dependsOn(MY_SQL_CONTAINER, FLYWAY)
59+
private static GenericContainer<?> buildAppContainer(final Network network, final Startable... dependsOn) {
60+
return new GenericContainer<>("app-test:integration")
61+
.dependsOn(dependsOn)
3562
.withNetwork(network)
63+
.withEnv("RANDOM_DATA_API_URL", "http://host.testcontainers.internal:" + MOCK_SERVER.port())
3664
.withEnv("MYSQL_USER", "test")
3765
.withEnv("MYSQL_PASSWORD", "test")
3866
.withEnv("MYSQL_URL", "jdbc:mysql://testdb:" + MySQLContainer.MYSQL_PORT + "/test?autoReconnect=true&useSSL=false")
3967
.withExposedPorts(8080)
4068
.waitingFor(Wait.forHttp("/health/ready").forStatusCode(200))
4169
.withLogConsumer(new Slf4jLogConsumer(LoggerFactory.getLogger("APP_CONTAINER")));
42-
43-
MY_SQL_CONTAINER.start();
44-
FLYWAY.start();
45-
APP.start();
46-
init();
4770
}
4871

4972

50-
private static void init() {
73+
private static void initRestAssured() {
5174
RestAssured.baseURI = "http://" + APP.getHost();
5275
RestAssured.port = APP.getFirstMappedPort();
5376
RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
5477
}
5578

79+
private static void exposeHostMachinePortToContainersForApiIntegrations() {
80+
Testcontainers.exposeHostPorts(MOCK_SERVER.port());
81+
}
5682

5783
}

acceptance-test/src/test/java/br/com/helpdev/atdd/ApplicationIT.java renamed to acceptance-test/src/test/java/br/com/helpdev/atdd/MessageV1EndpointIT.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package br.com.helpdev.atdd;
22

3+
import static br.com.helpdev.atdd.RandomDataApiMock.mockRandomIdNumber;
34
import static io.restassured.RestAssured.given;
5+
import static io.restassured.module.jsv.JsonSchemaValidator.matchesJsonSchemaInClasspath;
46
import static org.hamcrest.CoreMatchers.equalTo;
57
import static org.hamcrest.CoreMatchers.notNullValue;
68

@@ -11,10 +13,12 @@
1113
import java.time.ZonedDateTime;
1214
import org.junit.jupiter.api.Test;
1315

14-
class ApplicationIT extends AbstractContainerBaseTest {
16+
class MessageV1EndpointIT extends AbstractContainerBaseTest {
1517

1618
@Test
1719
void whenCreateNewScheduleThenReturn() {
20+
mockRandomIdNumber(MOCK_SERVER);
21+
1822
var now = ZonedDateTime.now();
1923
Integer id = given()
2024
.contentType(ContentType.JSON)
@@ -36,14 +40,16 @@ void whenCreateNewScheduleThenReturn() {
3640
.get("/v1/message/{id}", id)
3741
.then()
3842
.statusCode(200)
43+
.body("protocol", equalTo("000-22-1110"))
3944
.body("scheduleDate", notNullValue())
4045
.body("body", equalTo("Hello"))
4146
.body("channel", equalTo("WHATSAPP"))
4247
.body("recipient.name", equalTo("John James"))
4348
.body("recipient.phoneId", equalTo("123"))
4449
.body("recipient.email", equalTo("johm@jame.com"))
4550
.body("recipient.phoneNumber", equalTo("89898989"))
46-
.body("chats[0].status", equalTo("WAITING"));
51+
.body("chats[0].status", equalTo("WAITING"))
52+
.body(matchesJsonSchemaInClasspath("jsons/v1/postMessage.json"));
4753
}
4854

4955
@Test
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package br.com.helpdev.atdd;
2+
3+
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
4+
import static com.github.tomakehurst.wiremock.client.WireMock.get;
5+
import static com.github.tomakehurst.wiremock.client.WireMock.urlPathMatching;
6+
7+
import com.github.tomakehurst.wiremock.WireMockServer;
8+
9+
public class RandomDataApiMock {
10+
11+
public static void mockRandomIdNumber(final WireMockServer mockServer) {
12+
mockServer.stubFor(get(urlPathMatching("/api/id_number/random_id_number"))
13+
.willReturn(aResponse()
14+
.withBodyFile("random_id_number_response.json")
15+
.withStatus(200)
16+
.withHeader("Content-Type", "application/json")));
17+
}
18+
19+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"id": 8511,
3+
"uid": "2c6bbb23-8ad5-4e36-94d0-945f3fc541af",
4+
"valid_us_ssn": "000-22-1110",
5+
"invalid_us_ssn": "666-31-7707"
6+
}
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
{
2+
"definitions": {},
3+
"$schema": "http://json-schema.org/draft-07/schema#",
4+
"$id": "https://example.com/object1636888461.json",
5+
"title": "Root",
6+
"type": "object",
7+
"required": [
8+
"id",
9+
"protocol",
10+
"scheduleDate",
11+
"body",
12+
"recipient",
13+
"channel",
14+
"chats"
15+
],
16+
"properties": {
17+
"id": {
18+
"$id": "#root/id",
19+
"title": "Id",
20+
"type": "integer",
21+
"examples": [
22+
2
23+
],
24+
"default": 0
25+
},
26+
"protocol": {
27+
"$id": "#root/protocol",
28+
"title": "Protocol",
29+
"type": "string",
30+
"default": "",
31+
"examples": [
32+
"484-34-9572"
33+
],
34+
"pattern": "^.*$"
35+
},
36+
"scheduleDate": {
37+
"$id": "#root/scheduleDate",
38+
"title": "Scheduledate",
39+
"type": "string",
40+
"default": "",
41+
"examples": [
42+
"2022-01-01T00:00:00.000Z"
43+
],
44+
"pattern": "^.*$"
45+
},
46+
"body": {
47+
"$id": "#root/body",
48+
"title": "Body",
49+
"type": "string",
50+
"default": "",
51+
"examples": [
52+
"body"
53+
],
54+
"pattern": "^.*$"
55+
},
56+
"recipient": {
57+
"$id": "#root/recipient",
58+
"title": "Recipient",
59+
"type": "object",
60+
"required": [
61+
"name",
62+
"email",
63+
"phoneNumber",
64+
"phoneId"
65+
],
66+
"properties": {
67+
"name": {
68+
"$id": "#root/recipient/name",
69+
"title": "Name",
70+
"type": "string",
71+
"default": "",
72+
"examples": [
73+
"zarelli"
74+
],
75+
"pattern": "^.*$"
76+
},
77+
"email": {
78+
"$id": "#root/recipient/email",
79+
"title": "Email",
80+
"type": "string",
81+
"default": "",
82+
"examples": [
83+
"gbzarelli@gmail.com"
84+
],
85+
"pattern": "^.*$"
86+
},
87+
"phoneNumber": {
88+
"$id": "#root/recipient/phoneNumber",
89+
"title": "Phonenumber",
90+
"type": "string",
91+
"default": "",
92+
"examples": [
93+
"1231231231"
94+
],
95+
"pattern": "^.*$"
96+
},
97+
"phoneId": {
98+
"$id": "#root/recipient/phoneId",
99+
"title": "Phoneid",
100+
"type": "string",
101+
"default": "",
102+
"examples": [
103+
"16"
104+
],
105+
"pattern": "^.*$"
106+
}
107+
}
108+
}
109+
,
110+
"channel": {
111+
"$id": "#root/channel",
112+
"title": "Channel",
113+
"type": "string",
114+
"default": "",
115+
"examples": [
116+
"PUSH"
117+
],
118+
"pattern": "^.*$"
119+
},
120+
"chats": {
121+
"$id": "#root/chats",
122+
"title": "Chats",
123+
"type": "array",
124+
"default": [],
125+
"items":{
126+
"$id": "#root/chats/items",
127+
"title": "Items",
128+
"type": "object",
129+
"required": [
130+
"status",
131+
"date"
132+
],
133+
"properties": {
134+
"status": {
135+
"$id": "#root/chats/items/status",
136+
"title": "Status",
137+
"type": "string",
138+
"default": "",
139+
"examples": [
140+
"WAITING"
141+
],
142+
"pattern": "^.*$"
143+
},
144+
"date": {
145+
"$id": "#root/chats/items/date",
146+
"title": "Date",
147+
"type": "string",
148+
"default": "",
149+
"examples": [
150+
"2021-11-12T18:01:57.451-03:00"
151+
],
152+
"pattern": "^.*$"
153+
}
154+
}
155+
}
156+
157+
}
158+
}
159+
}

adapter/input/jaxrs-controller-v1/src/main/java/br/com/helpdev/controller/dto/MessageResponseDto.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
public class MessageResponseDto {
1212

1313
private Long id;
14+
private String protocol;
1415
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX")
1516
private ZonedDateTime scheduleDate;
1617
private String body;

adapter/input/jaxrs-controller-v1/src/main/java/br/com/helpdev/controller/mapper/ControllerMessageMapper.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ public class ControllerMessageMapper {
2626
public MessageResponseDto toDto(final Message message) {
2727
return MessageResponseDto.builder()
2828
.id(message.getId().map(MessageId::value).orElse(null))
29+
.protocol(message.getProtocol())
2930
.scheduleDate(message.getScheduleDate())
3031
.body(message.getBody().value())
3132
.channel(parse(message.getChannel()))

adapter/output/jpa-mysql-repository/src/main/java/br/com/helpdev/output/repository/entity/MessageEntity.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ public class MessageEntity {
3535
private ZonedDateTime scheduleDate;
3636
@Column(name = "message_body")
3737
private String body;
38+
@Column(name = "protocol")
39+
private String protocol;
3840
@Embedded
3941
private RecipientEntity recipient;
4042
@Column(name = "message_channel")

adapter/output/jpa-mysql-repository/src/main/java/br/com/helpdev/output/repository/mapper/MessageMapper.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ public MessageEntity toEntity(final Message message) {
3232
.channel(CommunicationChannelEntity.valueOf(message.getChannel().name()))
3333
.chats(toChatEntity(message.getChats()))
3434
.scheduleDate(message.getScheduleDate())
35+
.protocol(message.getProtocol())
3536
.recipient(RecipientEntity.builder()
3637
.email(message.getRecipient().getEmail())
3738
.name(message.getRecipient().getName())
@@ -48,6 +49,7 @@ public Message toDomain(final MessageEntity message) {
4849
.channel(CommunicationChannel.valueOf(message.getChannel().name()))
4950
.chats(toChatDomain(message.getChats()))
5051
.scheduleDate(message.getScheduleDate())
52+
.protocol(message.getProtocol())
5153
.recipient(Recipient.builder()
5254
.email(message.getRecipient().getEmail())
5355
.name(message.getRecipient().getName())

0 commit comments

Comments
 (0)