diff --git a/src/main/kotlin/cloud/cosmin/checklister/service/ListEvents.kt b/src/main/kotlin/cloud/cosmin/checklister/service/ListEvents.kt new file mode 100644 index 0000000..56be1a5 --- /dev/null +++ b/src/main/kotlin/cloud/cosmin/checklister/service/ListEvents.kt @@ -0,0 +1,8 @@ +package cloud.cosmin.checklister.service + +import cloud.cosmin.checklister.dto.ListGetDto + +interface ListEvents { + fun create(dto: ListGetDto) + fun update(before: ListGetDto, after: ListGetDto) +} \ No newline at end of file diff --git a/src/main/kotlin/cloud/cosmin/checklister/service/ListService.kt b/src/main/kotlin/cloud/cosmin/checklister/service/ListService.kt index 638ed0e..8da9371 100644 --- a/src/main/kotlin/cloud/cosmin/checklister/service/ListService.kt +++ b/src/main/kotlin/cloud/cosmin/checklister/service/ListService.kt @@ -5,6 +5,7 @@ import cloud.cosmin.checklister.dto.ListGetDto import cloud.cosmin.checklister.dto.ListPostDto import cloud.cosmin.checklister.dto.ListWithItemsDto import cloud.cosmin.checklister.repo.ListRepo +import cloud.cosmin.checklister.service.event.ListEventService import org.springframework.beans.factory.annotation.Autowired import org.springframework.stereotype.Service import java.util.* @@ -13,7 +14,8 @@ import java.util.* class ListService @Autowired constructor( private val listRepo: ListRepo, private val converterService: ConverterService, - private val uuidService: UuidService + private val uuidService: UuidService, + private val listEventService: ListEventService ) { fun findAll(): List { return listRepo.findAll() @@ -51,7 +53,9 @@ class ListService @Autowired constructor( newList.id = uuidService.get() newList.title = listPostDto.title val saved = listRepo.save(newList) - return converterService.listDto(saved) + val dto = converterService.listDto(saved) + listEventService.create(dto) + return dto } fun update(id: UUID, listPostDto: ListPostDto): Optional { @@ -61,9 +65,12 @@ class ListService @Autowired constructor( } val list = optionalList.get() + val beforeDto = converterService.listDto(list) list.title = listPostDto.title val saved = listRepo.save(list) - return Optional.of(converterService.listDto(saved)) + val afterDto = converterService.listDto(saved) + listEventService.update(beforeDto, afterDto) + return Optional.of(afterDto) } } \ No newline at end of file diff --git a/src/main/kotlin/cloud/cosmin/checklister/service/event/ItemEvent.kt b/src/main/kotlin/cloud/cosmin/checklister/service/event/ItemEvent.kt index e0ea56d..c7670e8 100644 --- a/src/main/kotlin/cloud/cosmin/checklister/service/event/ItemEvent.kt +++ b/src/main/kotlin/cloud/cosmin/checklister/service/event/ItemEvent.kt @@ -1,6 +1,7 @@ package cloud.cosmin.checklister.service.event import cloud.cosmin.checklister.dto.ItemGetDto +import cloud.cosmin.checklister.dto.ListGetDto import cloud.cosmin.checklister.service.RankOperation enum class ListEventType { @@ -18,9 +19,6 @@ abstract class AbstractEvent : Event { } } -data class ListCreateEvent( - val type: ItemEventType) - data class ItemCreateEvent(val item: ItemGetDto) : AbstractEvent() data class ItemUpdateEvent( @@ -30,4 +28,8 @@ data class ItemUpdateEvent( data class ItemRankEvent( val op: RankOperation, val before: ItemGetDto, - val after: ItemGetDto) : AbstractEvent() \ No newline at end of file + val after: ItemGetDto) : AbstractEvent() + +data class ListCreateEvent(val item: ListGetDto) : AbstractEvent() + +data class ListUpdateEvent(val before: ListGetDto, val after: ListGetDto) : AbstractEvent() \ No newline at end of file diff --git a/src/main/kotlin/cloud/cosmin/checklister/service/event/ItemEventService.kt b/src/main/kotlin/cloud/cosmin/checklister/service/event/ItemEventService.kt index be6976e..d797f2f 100644 --- a/src/main/kotlin/cloud/cosmin/checklister/service/event/ItemEventService.kt +++ b/src/main/kotlin/cloud/cosmin/checklister/service/event/ItemEventService.kt @@ -2,13 +2,15 @@ package cloud.cosmin.checklister.service.event import cloud.cosmin.checklister.dto.ItemGetDto import cloud.cosmin.checklister.service.RankOperation +import org.springframework.beans.factory.annotation.Autowired import org.springframework.stereotype.Service /** * Converts item actions into events. */ @Service -class ItemEventService(private val eventSink: EventSink) : ItemEvents { +class ItemEventService @Autowired +constructor(private val eventSink: EventSink) : ItemEvents { override fun create(dto: ItemGetDto) { val event = ItemCreateEvent(dto) eventSink.accept(event) diff --git a/src/main/kotlin/cloud/cosmin/checklister/service/event/ListEventService.kt b/src/main/kotlin/cloud/cosmin/checklister/service/event/ListEventService.kt new file mode 100644 index 0000000..edc4180 --- /dev/null +++ b/src/main/kotlin/cloud/cosmin/checklister/service/event/ListEventService.kt @@ -0,0 +1,20 @@ +package cloud.cosmin.checklister.service.event + +import cloud.cosmin.checklister.dto.ListGetDto +import cloud.cosmin.checklister.service.ListEvents +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.stereotype.Service + +@Service +class ListEventService @Autowired +constructor(private val eventSink: EventSink) : ListEvents { + override fun create(dto: ListGetDto) { + val event = ListCreateEvent(dto) + eventSink.accept(event) + } + + override fun update(before: ListGetDto, after: ListGetDto) { + val event = ListUpdateEvent(before, after) + eventSink.accept(event) + } +} \ No newline at end of file diff --git a/src/test/kotlin/cloud/cosmin/checklister/service/ListServiceTest.kt b/src/test/kotlin/cloud/cosmin/checklister/service/ListServiceTest.kt index a41070f..42a2af2 100644 --- a/src/test/kotlin/cloud/cosmin/checklister/service/ListServiceTest.kt +++ b/src/test/kotlin/cloud/cosmin/checklister/service/ListServiceTest.kt @@ -4,7 +4,9 @@ import cloud.cosmin.checklister.dao.ListEntity import cloud.cosmin.checklister.dto.ListGetDto import cloud.cosmin.checklister.dto.ListPostDto import cloud.cosmin.checklister.repo.ListRepo +import cloud.cosmin.checklister.service.event.ListEventService import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test import org.mockito.Mockito.* @@ -12,12 +14,23 @@ import java.util.* @DisplayName("ListService") internal class ListServiceTest { - @Test @DisplayName("should save lists") + val listRepo = mock(ListRepo::class.java) + val converterService = ConverterService() + val uuidService = mock(UuidService::class.java) + val listEventService = mock(ListEventService::class.java) + + fun createListService(): ListService { + return ListService(listRepo, converterService, uuidService, listEventService) + } + + @BeforeEach + fun setUp() { + reset(listRepo, uuidService, listEventService) + } + + @Test @DisplayName("should create lists") fun test01() { - val listRepo = mock(ListRepo::class.java) - val converterService = mock(ConverterService::class.java) - val uuidService = mock(UuidService::class.java) - val service = ListService(listRepo, converterService, uuidService) + val service = createListService() val uuid = UUID.randomUUID() val entity = ListEntity() @@ -28,11 +41,8 @@ internal class ListServiceTest { savedEntity.id = UUID.randomUUID() savedEntity.title = "title" - val listGetDto = ListGetDto(savedEntity.id, "title") - `when`(uuidService.get()).thenReturn(uuid) `when`(listRepo.save(entity)).thenReturn(savedEntity) - `when`(converterService.listDto(savedEntity)).thenReturn(listGetDto) val dto = ListPostDto("title") val createdDto = service.create(dto) @@ -44,10 +54,7 @@ internal class ListServiceTest { @Test @DisplayName("should update lists") fun test02() { - val listRepo = mock(ListRepo::class.java) - val converterService = mock(ConverterService::class.java) - val uuidService = mock(UuidService::class.java) - val service = ListService(listRepo, converterService, uuidService) + val service = createListService() val listId = UUID.randomUUID() @@ -59,11 +66,8 @@ internal class ListServiceTest { updatedList.id = dbList.id updatedList.title = "newTitle" - val listGetDto = ListGetDto(updatedList.id, "newTitle") - `when`(listRepo.findById(listId)).thenReturn(Optional.of(dbList)) `when`(listRepo.save(updatedList)).thenReturn(updatedList) - `when`(converterService.listDto(updatedList)).thenReturn(listGetDto) val listPostDto = ListPostDto("newTitle") @@ -73,4 +77,47 @@ internal class ListServiceTest { assertEquals(updatedList.id, updatedDto.get().id) assertEquals("newTitle", updatedDto.get().title) } + + @Test @DisplayName("should emit create events") + fun test03() { + val service = createListService() + + val uuid = UUID.randomUUID() + `when`(uuidService.get()).thenReturn(uuid) + + val listEntity = ListEntity() + listEntity.id = uuid + listEntity.title = "listTitle" + `when`(listRepo.save(listEntity)).thenReturn(listEntity) + + val post = ListPostDto("listTitle") + service.create(post) + + val listGetDto = ListGetDto(uuid, "listTitle") + verify(listEventService).create(listGetDto) + } + + @Test @DisplayName("should emit update events") + fun test04() { + val service = createListService() + + val uuid = UUID.randomUUID() + + val currentEntity = ListEntity() + currentEntity.id = uuid + currentEntity.title = "oldTitle" + `when`(listRepo.findById(uuid)).thenReturn(Optional.of(currentEntity)) + + val updatedEntity = ListEntity() + updatedEntity.id = uuid + updatedEntity.title = "newTitle" + `when`(listRepo.save(updatedEntity)).thenReturn(updatedEntity) + + val post = ListPostDto("newTitle") + service.update(uuid, post) + + val listBeforeDto = ListGetDto(currentEntity.id, "oldTitle") + val listAfterDto = ListGetDto(updatedEntity.id, "newTitle") + verify(listEventService).update(listBeforeDto, listAfterDto) + } } \ No newline at end of file