From efc27ac7276de9431e10d8a1cd80253db8d1dd27 Mon Sep 17 00:00:00 2001 From: Ralf Ueberfuhr Date: Wed, 20 Dec 2023 14:35:36 +0100 Subject: [PATCH 1/2] add blogpost initialization --- .../schulung/spring/blog/domain/BlogPost.java | 2 ++ .../spring/blog/domain/BlogPostCreatedEvent.java | 7 +++++++ .../spring/blog/domain/BlogPostEventLogger.java | 16 ++++++++++++++++ .../spring/blog/domain/BlogPostService.java | 5 +++++ src/main/resources/application.yml | 3 +++ 5 files changed, 33 insertions(+) create mode 100644 src/main/java/de/sample/schulung/spring/blog/domain/BlogPostCreatedEvent.java create mode 100644 src/main/java/de/sample/schulung/spring/blog/domain/BlogPostEventLogger.java diff --git a/src/main/java/de/sample/schulung/spring/blog/domain/BlogPost.java b/src/main/java/de/sample/schulung/spring/blog/domain/BlogPost.java index 0469cc8..0372dfe 100644 --- a/src/main/java/de/sample/schulung/spring/blog/domain/BlogPost.java +++ b/src/main/java/de/sample/schulung/spring/blog/domain/BlogPost.java @@ -5,6 +5,7 @@ import lombok.Builder; import lombok.Getter; import lombok.Setter; +import lombok.ToString; import java.time.LocalDateTime; import java.util.UUID; @@ -12,6 +13,7 @@ @Builder @Getter @Setter +@ToString public class BlogPost { private UUID id; diff --git a/src/main/java/de/sample/schulung/spring/blog/domain/BlogPostCreatedEvent.java b/src/main/java/de/sample/schulung/spring/blog/domain/BlogPostCreatedEvent.java new file mode 100644 index 0000000..fd46125 --- /dev/null +++ b/src/main/java/de/sample/schulung/spring/blog/domain/BlogPostCreatedEvent.java @@ -0,0 +1,7 @@ +package de.sample.schulung.spring.blog.domain; + +public record BlogPostCreatedEvent( + BlogPost blogPost +) { + +} diff --git a/src/main/java/de/sample/schulung/spring/blog/domain/BlogPostEventLogger.java b/src/main/java/de/sample/schulung/spring/blog/domain/BlogPostEventLogger.java new file mode 100644 index 0000000..c725fa5 --- /dev/null +++ b/src/main/java/de/sample/schulung/spring/blog/domain/BlogPostEventLogger.java @@ -0,0 +1,16 @@ +package de.sample.schulung.spring.blog.domain; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; + +@Component +@Slf4j +public class BlogPostEventLogger { + + @EventListener + void logBlogPostCreated(BlogPostCreatedEvent evt) { + log.debug("BlogPost created: {}", evt.blogPost()); + } + +} diff --git a/src/main/java/de/sample/schulung/spring/blog/domain/BlogPostService.java b/src/main/java/de/sample/schulung/spring/blog/domain/BlogPostService.java index 2592dc6..ef3f880 100644 --- a/src/main/java/de/sample/schulung/spring/blog/domain/BlogPostService.java +++ b/src/main/java/de/sample/schulung/spring/blog/domain/BlogPostService.java @@ -2,6 +2,8 @@ import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; +import lombok.RequiredArgsConstructor; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -14,9 +16,11 @@ @Validated @Service +@RequiredArgsConstructor public class BlogPostService { private final Map blogPosts = new HashMap<>(); + private final ApplicationEventPublisher eventPublisher; public long count() { return blogPosts.size(); @@ -37,6 +41,7 @@ public void create(@Valid @NotNull BlogPost blogPost) { blogPost.setId(id); blogPost.setTimestamp(LocalDateTime.now()); this.blogPosts.put(id, blogPost); + this.eventPublisher.publishEvent(new BlogPostCreatedEvent(blogPost)); } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 626ada3..1b0d8dd 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,2 +1,5 @@ server: port: ${SERVER_PORT:9080} +logging: + level: + de.sample.schulung.spring.blog.domain.BlogPostEventLogger: debug From 172bd56690783d8b5a267211b8c3a5c5758130d5 Mon Sep 17 00:00:00 2001 From: Ralf Ueberfuhr Date: Wed, 20 Dec 2023 15:05:13 +0100 Subject: [PATCH 2/2] add tests for blogpost initialization --- .../boundary/BlogPostControllerTests.java | 7 ++- .../blog/domain/BlogPostEventsTests.java | 50 +++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 src/test/java/de/sample/schulung/spring/blog/domain/BlogPostEventsTests.java diff --git a/src/test/java/de/sample/schulung/spring/blog/boundary/BlogPostControllerTests.java b/src/test/java/de/sample/schulung/spring/blog/boundary/BlogPostControllerTests.java index 611e0c0..1100257 100644 --- a/src/test/java/de/sample/schulung/spring/blog/boundary/BlogPostControllerTests.java +++ b/src/test/java/de/sample/schulung/spring/blog/boundary/BlogPostControllerTests.java @@ -3,6 +3,8 @@ import de.sample.schulung.spring.blog.domain.BlogPostService; import org.junit.jupiter.api.Test; import org.mapstruct.factory.Mappers; +import org.mockito.Mockito; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.http.HttpStatus; import static org.assertj.core.api.Assertions.assertThat; @@ -11,7 +13,8 @@ public class BlogPostControllerTests { @Test void shouldCreateBlogPostSuccessfully() { - final var service = new BlogPostService(); + final var eventPublisher = Mockito.mock(ApplicationEventPublisher.class); + final var service = new BlogPostService(eventPublisher); final var mapper = Mappers.getMapper(BlogPostDtoMapper.class); final var controller = new BlogPostController(service, mapper); final var blogPost = new BlogPostDto(); @@ -27,6 +30,8 @@ void shouldCreateBlogPostSuccessfully() { assertThat(result.getBody().getTitle()) .isEqualTo(blogPost.getTitle()); + // TODO verify eventPublisher.publishEvent? + } } diff --git a/src/test/java/de/sample/schulung/spring/blog/domain/BlogPostEventsTests.java b/src/test/java/de/sample/schulung/spring/blog/domain/BlogPostEventsTests.java new file mode 100644 index 0000000..90ffd61 --- /dev/null +++ b/src/test/java/de/sample/schulung/spring/blog/domain/BlogPostEventsTests.java @@ -0,0 +1,50 @@ +package de.sample.schulung.spring.blog.domain; + +import jakarta.validation.ConstraintViolationException; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.event.ApplicationEvents; +import org.springframework.test.context.event.RecordApplicationEvents; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@SpringBootTest +@RecordApplicationEvents +public class BlogPostEventsTests { + + @Autowired + BlogPostService service; + @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") + @Autowired + ApplicationEvents events; + + @Test + void shouldPublishEventOnCreate() { + final var newBlogPost = BlogPost + .builder() + .title("test") + .content("test content with 10 chars") + .build(); + service.create(newBlogPost); + + assertThat(events.stream(BlogPostCreatedEvent.class)) + .hasSize(1) + .first() + .extracting(BlogPostCreatedEvent::blogPost) + .isSameAs(newBlogPost); + } + + @Test + void shouldNotPublishEventOnInvalidCreate() { + final var newBlogPost = BlogPost + .builder() + .content("test content with 10 chars") + .build(); + assertThatThrownBy(() -> service.create(newBlogPost)) + .isInstanceOf(ConstraintViolationException.class); + assertThat(events.stream(BlogPostCreatedEvent.class)) + .isEmpty(); + } +}