-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from sipios/test/add-unit-tests
test: add unit tests for DataEventBroadcaster and DataEventListener
- Loading branch information
Showing
4 changed files
with
336 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
name: Test & Coverage | ||
on: | ||
pull_request: | ||
branches: | ||
- '*' | ||
|
||
jobs: | ||
test-and-coverage: | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- uses: actions/checkout@v3 | ||
|
||
- name: Set up JDK 21 | ||
uses: actions/setup-java@v3 | ||
with: | ||
java-version: '21' | ||
distribution: 'temurin' | ||
|
||
- name: Set up the Maven dependencies caching | ||
uses: actions/cache@v3 | ||
with: | ||
path: ~/.m2 | ||
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} | ||
restore-keys: ${{ runner.os }}-m2 | ||
|
||
- name: Run tests | ||
run: mvn --batch-mode --update-snapshots verify -Dgpg.skip=true | ||
|
||
- name: Add coverage | ||
uses: madrapps/[email protected] | ||
with: | ||
paths: | | ||
${{ github.workspace }}/**/target/site/jacoco/jacoco.xml | ||
token: ${{ secrets.GITHUB_TOKEN }} | ||
title: '### :zap: Coverage report' | ||
update-comment: true | ||
min-coverage-overall: 80 | ||
min-coverage-changed-files: 60 | ||
continue-on-error: false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,6 +26,7 @@ | |
|
||
<properties> | ||
<java.version>21</java.version> | ||
<mockito.version>4.11.0</mockito.version> | ||
</properties> | ||
|
||
<dependencies> | ||
|
@@ -58,6 +59,18 @@ | |
<artifactId>spring-kafka-test</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.springframework.boot</groupId> | ||
<artifactId>spring-boot-starter-test</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.mockito</groupId> | ||
<artifactId>mockito-core</artifactId> | ||
<version>${mockito.version}</version> | ||
<scope>test</scope> | ||
</dependency> | ||
|
||
</dependencies> | ||
|
||
<build> | ||
|
@@ -122,9 +135,27 @@ | |
<failOnError>false</failOnError> | ||
</configuration> | ||
</plugin> | ||
<plugin> | ||
<groupId>org.jacoco</groupId> | ||
<artifactId>jacoco-maven-plugin</artifactId> | ||
<version>0.8.12</version> | ||
<executions> | ||
<execution> | ||
<goals> | ||
<goal>prepare-agent</goal> | ||
</goals> | ||
</execution> | ||
<execution> | ||
<id>report</id> | ||
<phase>test</phase> | ||
<goals> | ||
<goal>report</goal> | ||
</goals> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
|
||
<scm> | ||
<connection>scm:git:https://github.com/sipios/spring-data-event.git</connection> | ||
<developerConnection>scm:git:[email protected]:sipios/spring-data-event.git</developerConnection> | ||
|
113 changes: 113 additions & 0 deletions
113
src/test/java/com/sipios/spring/data/event/broadcaster/DataEventBroadcasterTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
package com.sipios.spring.data.event.broadcaster; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertThrows; | ||
import static org.mockito.Mockito.*; | ||
|
||
import com.fasterxml.jackson.core.JsonProcessingException; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
import lombok.Setter; | ||
import org.hibernate.CallbackException; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.params.ParameterizedTest; | ||
import org.junit.jupiter.params.provider.CsvSource; | ||
import org.springframework.kafka.core.KafkaTemplate; | ||
|
||
public class DataEventBroadcasterTest { | ||
private DataEventBroadcaster broadcaster; | ||
private KafkaTemplate<String, String> kafkaTemplate; | ||
private ObjectMapper objectMapper; | ||
|
||
@BeforeEach | ||
void beforeEach() { | ||
kafkaTemplate = mock(KafkaTemplate.class); | ||
objectMapper = new ObjectMapper(); | ||
broadcaster = new DataEventBroadcaster(kafkaTemplate, objectMapper); | ||
} | ||
|
||
@ParameterizedTest | ||
@CsvSource({ | ||
"testEntity.created, testEntity.created", | ||
"'', testentity.created" | ||
}) | ||
void testBroadcastEntityCreated(String topicLabel, String expectedTopic) throws Exception { | ||
TestEntity entity = new TestEntity(1, "Test Name", true); | ||
String expectedJson = objectMapper.writeValueAsString(entity); | ||
|
||
broadcaster.broadcastEntityCreated(entity, topicLabel); | ||
|
||
verify(kafkaTemplate).send(eq(expectedTopic), eq(expectedJson)); | ||
} | ||
|
||
@ParameterizedTest | ||
@CsvSource({ | ||
"testEntity.updated, testEntity.updated", | ||
"'', testentity.updated" | ||
}) | ||
void testBroadcastEntityUpdated(String topicLabel, String expectedTopic) throws Exception { | ||
TestEntity entity = new TestEntity(1, "Test Name", false); | ||
String expectedJson = objectMapper.writeValueAsString(entity); | ||
|
||
broadcaster.broadcastEntityUpdated(entity, topicLabel); | ||
|
||
verify(kafkaTemplate).send(eq(expectedTopic), eq(expectedJson)); | ||
} | ||
|
||
@ParameterizedTest | ||
@CsvSource({ | ||
"testEntity.deleted, testEntity.deleted", | ||
"'', testentity.deleted" | ||
}) | ||
void testBroadcastEntityDeleted(String topicLabel, String expectedTopic) throws Exception { | ||
TestEntity entity = new TestEntity(1, "Test Name", true); | ||
String expectedJson = objectMapper.writeValueAsString(entity); | ||
|
||
broadcaster.broadcastEntityDeleted(entity, topicLabel); | ||
|
||
verify(kafkaTemplate).send(eq(expectedTopic), eq(expectedJson)); | ||
} | ||
|
||
@Test | ||
void testBroadcastEntityCreatedJsonProcessingException() throws Exception { | ||
objectMapper = mock(ObjectMapper.class); | ||
broadcaster = new DataEventBroadcaster(kafkaTemplate, objectMapper); | ||
TestEntity entity = new TestEntity(1, "Test Name", true); | ||
|
||
when(objectMapper.writeValueAsString(entity)).thenThrow(new JsonProcessingException("JSON processing error") {}); | ||
|
||
assertThrows(CallbackException.class, () -> broadcaster.broadcastEntityCreated(entity, "testEntity.created")); | ||
} | ||
|
||
@Test | ||
void testBroadcastEntityUpdatedJsonProcessingException() throws Exception { | ||
objectMapper = mock(ObjectMapper.class); | ||
broadcaster = new DataEventBroadcaster(kafkaTemplate, objectMapper); | ||
TestEntity entity = new TestEntity(1, "Test Name", false); | ||
|
||
when(objectMapper.writeValueAsString(entity)).thenThrow(new JsonProcessingException("JSON processing error") {}); | ||
|
||
assertThrows(CallbackException.class, () -> broadcaster.broadcastEntityUpdated(entity, "testEntity.updated")); | ||
} | ||
|
||
@Test | ||
void testBroadcastEntityDeletedJsonProcessingException() throws Exception { | ||
objectMapper = mock(ObjectMapper.class); | ||
broadcaster = new DataEventBroadcaster(kafkaTemplate, objectMapper); | ||
TestEntity entity = new TestEntity(1, "Test Name", true); | ||
|
||
when(objectMapper.writeValueAsString(entity)).thenThrow(new JsonProcessingException("JSON processing error") {}); | ||
|
||
assertThrows(CallbackException.class, () -> broadcaster.broadcastEntityDeleted(entity, "testEntity.deleted")); | ||
} | ||
|
||
@Getter | ||
@Setter | ||
@AllArgsConstructor | ||
public static class TestEntity { | ||
private int id; | ||
private String name; | ||
private boolean active; | ||
} | ||
} |
151 changes: 151 additions & 0 deletions
151
src/test/java/com/sipios/spring/data/event/listener/DataEventListenerTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
package com.sipios.spring.data.event.listener; | ||
|
||
import com.sipios.spring.data.event.annotation.DataEventEntity; | ||
import com.sipios.spring.data.event.broadcaster.DataEventBroadcaster; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
import lombok.Setter; | ||
import org.hibernate.event.spi.PostDeleteEvent; | ||
import org.hibernate.event.spi.PostInsertEvent; | ||
import org.hibernate.event.spi.PostUpdateEvent; | ||
import org.junit.jupiter.api.Nested; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.extension.ExtendWith; | ||
import org.mockito.InjectMocks; | ||
import org.mockito.Mock; | ||
import org.mockito.junit.jupiter.MockitoExtension; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertThrows; | ||
import static org.mockito.Mockito.*; | ||
|
||
@ExtendWith(MockitoExtension.class) | ||
public class DataEventListenerTest { | ||
@Mock | ||
private DataEventBroadcaster dataEventBroadcaster; | ||
|
||
@InjectMocks | ||
private DataEventListener listener; | ||
|
||
@Nested | ||
class AnnotatedEntityTests { | ||
|
||
@Test | ||
public void testOnPostInsert() { | ||
PostInsertEvent event = mock(PostInsertEvent.class); | ||
TestEntity entity = new TestEntity(1, "Test Name", true); | ||
when(event.getEntity()).thenReturn(entity); | ||
|
||
listener.onPostInsert(event); | ||
|
||
verify(dataEventBroadcaster).broadcastEntityCreated(entity, "testEntity.created"); | ||
} | ||
|
||
@Test | ||
public void testOnPostUpdate() { | ||
PostUpdateEvent event = mock(PostUpdateEvent.class); | ||
TestEntity entity = new TestEntity(1, "Test Name", true); | ||
when(event.getEntity()).thenReturn(entity); | ||
|
||
listener.onPostUpdate(event); | ||
|
||
verify(dataEventBroadcaster).broadcastEntityUpdated(entity, "testEntity.updated"); | ||
} | ||
|
||
@Test | ||
public void testOnPostDelete() { | ||
PostDeleteEvent event = mock(PostDeleteEvent.class); | ||
TestEntity entity = new TestEntity(1, "Test Name", true); | ||
when(event.getEntity()).thenReturn(entity); | ||
|
||
listener.onPostDelete(event); | ||
|
||
verify(dataEventBroadcaster).broadcastEntityDeleted(entity, "testEntity.deleted"); | ||
} | ||
|
||
@Test | ||
public void testOnPostInsertJsonProcessingException() throws Exception { | ||
PostInsertEvent event = mock(PostInsertEvent.class); | ||
TestEntity entity = new TestEntity(1, "Test Name", true); | ||
when(event.getEntity()).thenReturn(entity); | ||
doThrow(new RuntimeException("JSON processing error")).when(dataEventBroadcaster).broadcastEntityCreated(any(), any()); | ||
|
||
assertThrows(RuntimeException.class, () -> listener.onPostInsert(event)); | ||
} | ||
|
||
@Test | ||
public void testOnPostUpdateJsonProcessingException() throws Exception { | ||
PostUpdateEvent event = mock(PostUpdateEvent.class); | ||
TestEntity entity = new TestEntity(1, "Test Name", true); | ||
when(event.getEntity()).thenReturn(entity); | ||
doThrow(new RuntimeException("JSON processing error")).when(dataEventBroadcaster).broadcastEntityUpdated(any(), any()); | ||
|
||
assertThrows(RuntimeException.class, () -> listener.onPostUpdate(event)); | ||
} | ||
|
||
@Test | ||
public void testOnPostDeleteJsonProcessingException() throws Exception { | ||
PostDeleteEvent event = mock(PostDeleteEvent.class); | ||
TestEntity entity = new TestEntity(1, "Test Name", true); | ||
when(event.getEntity()).thenReturn(entity); | ||
doThrow(new RuntimeException("JSON processing error")).when(dataEventBroadcaster).broadcastEntityDeleted(any(), any()); | ||
|
||
assertThrows(RuntimeException.class, () -> listener.onPostDelete(event)); | ||
} | ||
|
||
@DataEventEntity(creationTopic = "testEntity.created", updateTopic = "testEntity.updated", deletionTopic = "testEntity.deleted") | ||
@Getter | ||
@Setter | ||
@AllArgsConstructor | ||
private static class TestEntity { | ||
private int id; | ||
private String name; | ||
private boolean active; | ||
} | ||
} | ||
|
||
@Nested | ||
class NonAnnotatedEntityTests { | ||
|
||
@Test | ||
public void testOnPostInsert() { | ||
PostInsertEvent event = mock(PostInsertEvent.class); | ||
NonAnnotatedEntity entity = new NonAnnotatedEntity(1, "Test Name", true); | ||
when(event.getEntity()).thenReturn(entity); | ||
|
||
listener.onPostInsert(event); | ||
|
||
verify(dataEventBroadcaster, never()).broadcastEntityCreated(any(), any()); | ||
} | ||
|
||
@Test | ||
public void testOnPostUpdate() { | ||
PostUpdateEvent event = mock(PostUpdateEvent.class); | ||
NonAnnotatedEntity entity = new NonAnnotatedEntity(1, "Test Name", true); | ||
when(event.getEntity()).thenReturn(entity); | ||
|
||
listener.onPostUpdate(event); | ||
|
||
verify(dataEventBroadcaster, never()).broadcastEntityUpdated(any(), any()); | ||
} | ||
|
||
@Test | ||
public void testOnPostDelete() { | ||
PostDeleteEvent event = mock(PostDeleteEvent.class); | ||
NonAnnotatedEntity entity = new NonAnnotatedEntity(1, "Test Name", true); | ||
when(event.getEntity()).thenReturn(entity); | ||
|
||
listener.onPostDelete(event); | ||
|
||
verify(dataEventBroadcaster, never()).broadcastEntityDeleted(any(), any()); | ||
} | ||
|
||
@Getter | ||
@Setter | ||
@AllArgsConstructor | ||
private static class NonAnnotatedEntity { | ||
private int id; | ||
private String name; | ||
private boolean active; | ||
} | ||
} | ||
} |