Skip to content

Commit

Permalink
[Webhook] Write Test for Webhook module (#969)
Browse files Browse the repository at this point in the history
  • Loading branch information
minhtranq-nashtechglobal committed Sep 17, 2024
1 parent 06f5ee2 commit 6b63856
Show file tree
Hide file tree
Showing 10 changed files with 2,174 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

import com.yas.media.config.IntegrationTestConfiguration;
import com.yas.media.config.FilesystemConfig;
import com.yas.media.config.YasConfig;
import com.yas.media.model.Media;
import com.yas.media.repository.FileSystemRepository;
import com.yas.media.repository.MediaRepository;
import com.yas.media.service.MediaService;
import com.yas.media.repository.MediaRepository;
import com.yas.media.viewmodel.MediaPostVm;
import com.yas.media.config.IntegrationTestConfiguration;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
Expand Down
5 changes: 5 additions & 0 deletions webhook/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>kafka</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.yas.webhook.config;

import dasniko.testcontainers.keycloak.KeycloakContainer;
import java.util.HashMap;
import java.util.Map;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.testcontainers.containers.KafkaContainer;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.utility.DockerImageName;

@TestConfiguration
public class IntegrationTestConfiguration implements ApplicationContextInitializer<ConfigurableApplicationContext> {

@ServiceConnection
@Bean(destroyMethod = "stop")
public PostgreSQLContainer<?> postgresContainer() {
return new PostgreSQLContainer<>("postgres:16")
.withDatabaseName("integration-tests-db")
.withReuse(true);
}

@Bean(destroyMethod = "stop")
public KeycloakContainer keycloakContainer(DynamicPropertyRegistry registry) {
KeycloakContainer keycloak = new KeycloakContainer()
.withRealmImportFiles("/test-realm.json")
.withReuse(true);

registry.add("spring.security.oauth2.resourceserver.jwt.issuer-uri",
() -> keycloak.getAuthServerUrl() + "/realms/quarkus");
registry.add("spring.security.oauth2.resourceserver.jwt.jwk-set-uri",
() -> keycloak.getAuthServerUrl() + "/realms/quarkus/protocol/openid-connect/certs");
return keycloak;
}

@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
ConfigurableEnvironment environment = applicationContext.getEnvironment();
KafkaContainer kafka = new KafkaContainer(
DockerImageName.parse("confluentinc/cp-kafka:7.2.2.arm64"));
kafka.start();
setProperties(environment, "spring.kafka.bootstrap-servers", kafka.getBootstrapServers());
}

private void setProperties(ConfigurableEnvironment environment, String name, Object value) {
MutablePropertySources sources = environment.getPropertySources();
PropertySource<?> source = sources.get(name);
if (source == null) {
source = new MapPropertySource(name, new HashMap<>());
sources.addFirst(source);
}
((Map<String, Object>) source.getSource()).put(name, value);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.yas.webhook.controller;

import static io.restassured.RestAssured.given;

import io.restassured.RestAssured;
import io.restassured.builder.RequestSpecBuilder;
import io.restassured.specification.RequestSpecification;
import java.util.Map;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.http.MediaType;
import org.testcontainers.shaded.com.google.common.net.HttpHeaders;

public class AbstractControllerIT {

@Value("${spring.security.oauth2.resourceserver.jwt.issuer-uri}")
protected String authServerUrl;

@LocalServerPort
private int port;

protected RequestSpecification getRequestSpecification() {
RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
return new RequestSpecBuilder()
.setPort(port)
.addHeader(
HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_JSON_VALUE
)
.build();
}

protected String getAccessToken(String username, String password) {
return given()
.contentType("application/x-www-form-urlencoded")
.formParams(Map.of(
"username", username,
"password", password,
"scope", "openid",
"grant_type", "password",
"client_id", "quarkus-service",
"client_secret", "secret"
))
.post(authServerUrl + "/protocol/openid-connect/token")
.then().assertThat().statusCode(200)
.extract().path("access_token");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
package com.yas.webhook.controller;

import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.equalTo;

import com.yas.webhook.config.IntegrationTestConfiguration;
import com.yas.webhook.config.constants.ApiConstant;
import com.yas.webhook.model.Event;
import com.yas.webhook.model.Webhook;
import com.yas.webhook.model.WebhookEvent;
import com.yas.webhook.model.enums.EventName;
import com.yas.webhook.repository.EventRepository;
import com.yas.webhook.repository.WebhookEventRepository;
import com.yas.webhook.repository.WebhookRepository;
import com.yas.webhook.service.WebhookService;
import io.restassured.http.ContentType;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
import org.springframework.http.HttpStatus;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@EnableTransactionManagement
@Import(IntegrationTestConfiguration.class)
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@PropertySource("classpath:application.properties")
public class WebhookControllerIT extends AbstractControllerIT {

@Autowired
private WebhookService service;
@Autowired
private WebhookRepository webhookRepository;
@Autowired
private EventRepository eventRepository;
@Autowired
private WebhookEventRepository webhookEventRepository;

private static final String WEBHOOK_URL = "/webhook" + ApiConstant.WEBHOOK_URL;

@BeforeEach
public void init() {
Webhook webhook = new Webhook();
webhook.setContentType("application/json");
Webhook persistedWebhook = webhookRepository.save(webhook);

Event event = new Event();
event.setName(EventName.ON_PRODUCT_UPDATED);
Event persistedEvent = eventRepository.save(event);

WebhookEvent webhookEvent = new WebhookEvent();
webhookEvent.setWebhookId(persistedWebhook.getId());
webhookEvent.setEventId(persistedEvent.getId());

webhookEventRepository.save(webhookEvent);
}

@Test
public void test_createWebhook_shouldSuccess() {
given(getRequestSpecification())
.auth().oauth2(getAccessToken("admin", "admin"))
.contentType(ContentType.JSON)
.body("""
{"id":1,"payloadUrl":"","secret":"","contentType":"","isActive":true
,"events":[{"id":1,"name":"ON_PRODUCT_UPDATED"}]}
""")
.when()
.post(WEBHOOK_URL)
.then()
.statusCode(HttpStatus.CREATED.value())
.log().ifValidationFails();
}

@Test
public void test_updateWebhook_shouldSuccess() {
given(getRequestSpecification())
.auth().oauth2(getAccessToken("admin", "admin"))
.contentType(ContentType.JSON)
.body("""
{"id":1,"payloadUrl":"","secret":"","contentType":"","isActive":true
,"events":[{"id":1,"name":"ON_PRODUCT_UPDATED"}]}
""")
.pathParam("id", 1)
.when()
.put(WEBHOOK_URL + "/{id}")
.then()
.statusCode(HttpStatus.NO_CONTENT.value())
.log().ifValidationFails();
}

@Test
public void test_deleteWebhook_shouldSuccess() {
given(getRequestSpecification())
.auth().oauth2(getAccessToken("admin", "admin"))
.contentType(ContentType.JSON)
.pathParam("id", 1)
.when()
.delete(WEBHOOK_URL + "/{id}")
.then()
.statusCode(HttpStatus.NO_CONTENT.value())
.log().ifValidationFails();
}

@Test
public void test_getWebhook_shouldReturnSuccessfully() {
given(getRequestSpecification())
.auth().oauth2(getAccessToken("admin", "admin"))
.contentType(ContentType.JSON)
.pathParam("id", 1)
.when()
.get(WEBHOOK_URL + "/{id}")
.then()
.statusCode(HttpStatus.OK.value())
.body("contentType", equalTo("application/json"))
.log().ifValidationFails();
}

@Test
public void test_listWebhooks_shouldReturnSuccessfully() {
given(getRequestSpecification())
.auth().oauth2(getAccessToken("admin", "admin"))
.contentType(ContentType.JSON)
.when()
.get(WEBHOOK_URL)
.then()
.statusCode(HttpStatus.OK.value())
.log().ifValidationFails();
}

@Test
public void test_getPageableWebhooks_shouldReturnSuccessfully() {
given(getRequestSpecification())
.auth().oauth2(getAccessToken("admin", "admin"))
.contentType(ContentType.JSON)
.when()
.get(WEBHOOK_URL + "/paging")
.then()
.statusCode(HttpStatus.OK.value())
.body("pageNo", equalTo(0))
.body("pageSize", equalTo(10))
.body("totalElements", equalTo(4))
.body("totalPages", equalTo(1))
.log().ifValidationFails();
}
}
29 changes: 29 additions & 0 deletions webhook/src/it/resources/application.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Setting Spring context path & port
server.servlet.context-path=/webhook
server.port=8092

spring.application.name=webhook

# Setting Spring profile
spring.profiles.active=test

spring.datasource.url=jdbc:postgres:16:///integration-tests-db
spring.datasource.driver-class-name=org.testcontainers.jdbc.ContainerDatabaseDriver
spring.jpa.hibernate.ddl-auto=update
spring.liquibase.enabled=false

spring.security.oauth2.resourceserver.jwt.issuer-uri=test
springdoc.oauthflow.authorization-url=test
springdoc.oauthflow.token-url=test
spring.jpa.open-in-view=true
file.directory=images

spring.kafka.bootstrap-servers=localhost:9092
spring.kafka.consumer.group-id=webhook
spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer
spring.kafka.consumer.value-deserializer=org.apache.kafka.common.serialization.ByteArrayDeserializer

spring.kafka.consumer.properties.spring.json.use.type.headers=false

webhook.integration.kafka.product.topic-name=dbproduct.public.product
webhook.integration.kafka.order.topic-name=dborder.public.order
16 changes: 16 additions & 0 deletions webhook/src/it/resources/logback-spring.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml" />
<springProperty scope="context" name="appName" source="spring.application.name"/>

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>

<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
</configuration>

Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
mock-maker-inline

Loading

0 comments on commit 6b63856

Please sign in to comment.