You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by ma...@apache.org on 2020/02/27 16:20:28 UTC
[james-project] 07/14: JAMES-3009 convert event sourcing core tests
to scala
This is an automated email from the ASF dual-hosted git repository.
matthieu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 929e958a479fe7062240ffe0717b85afba08aeb2
Author: RĂ©mi KOWALSKI <rk...@linagora.com>
AuthorDate: Wed Dec 11 16:08:28 2019 +0100
JAMES-3009 convert event sourcing core tests to scala
---
.../eventsourcing/DataCollectorSubscriber.java | 46 ----
.../eventsourcing/EventSourcingSystemTest.java | 259 ---------------------
.../eventsourcing/EventSourcingSystemTest.scala | 167 +++++++++++++
3 files changed, 167 insertions(+), 305 deletions(-)
diff --git a/event-sourcing/event-sourcing-core/src/test/java/org/apache/james/eventsourcing/DataCollectorSubscriber.java b/event-sourcing/event-sourcing-core/src/test/java/org/apache/james/eventsourcing/DataCollectorSubscriber.java
deleted file mode 100644
index 85fccd1..0000000
--- a/event-sourcing/event-sourcing-core/src/test/java/org/apache/james/eventsourcing/DataCollectorSubscriber.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.eventsourcing;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import com.google.common.collect.ImmutableList;
-
-public class DataCollectorSubscriber implements Subscriber {
-
- private final List<String> data;
-
- public DataCollectorSubscriber() {
- data = new ArrayList<>();
- }
-
- @Override
- public void handle(Event event) {
- if (event instanceof TestEvent) {
- data.add(((TestEvent) event).getData());
- }
- }
-
-
- public List<String> getData() {
- return ImmutableList.copyOf(data);
- }
-}
diff --git a/event-sourcing/event-sourcing-core/src/test/java/org/apache/james/eventsourcing/EventSourcingSystemTest.java b/event-sourcing/event-sourcing-core/src/test/java/org/apache/james/eventsourcing/EventSourcingSystemTest.java
deleted file mode 100644
index 5e431d6..0000000
--- a/event-sourcing/event-sourcing-core/src/test/java/org/apache/james/eventsourcing/EventSourcingSystemTest.java
+++ /dev/null
@@ -1,259 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.eventsourcing;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import org.apache.james.eventsourcing.eventstore.EventStore;
-import org.apache.james.eventsourcing.eventstore.History;
-import org.junit.jupiter.api.Test;
-import org.mockito.internal.matchers.InstanceOf;
-import org.mockito.internal.progress.ThreadSafeMockingProgress;
-
-import com.github.steveash.guavate.Guavate;
-import com.google.common.base.Splitter;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import scala.collection.immutable.List;
-import scala.jdk.javaapi.CollectionConverters;
-
-public interface EventSourcingSystemTest {
-
- String PAYLOAD_1 = "payload1";
- String PAYLOAD_2 = "payload2";
- TestAggregateId AGGREGATE_ID = TestAggregateId.apply(42);
-
- class MyCommand implements Command {
- private final String payload;
-
- public MyCommand(String payload) {
- this.payload = payload;
- }
-
- public String getPayload() {
- return payload;
- }
- }
-
- @Test
- default void dispatchShouldApplyCommandHandlerThenCallSubscribers(EventStore eventStore) {
- DataCollectorSubscriber subscriber = new DataCollectorSubscriber();
- EventSourcingSystem eventSourcingSystem = EventSourcingSystem.fromJava(
- ImmutableSet.of(simpleDispatcher(eventStore)),
- ImmutableSet.of(subscriber),
- eventStore);
-
- eventSourcingSystem.dispatch(new MyCommand(PAYLOAD_1));
-
- assertThat(subscriber.getData()).containsExactly(PAYLOAD_1);
- }
-
- @Test
- default void throwingSubscribersShouldNotAbortSubscriberChain(EventStore eventStore) {
- DataCollectorSubscriber subscriber = new DataCollectorSubscriber();
- EventSourcingSystem eventSourcingSystem = EventSourcingSystem.fromJava(
- ImmutableSet.of(simpleDispatcher(eventStore)),
- ImmutableSet.of(
- events -> {
- throw new RuntimeException();
- },
- subscriber),
- eventStore);
-
- eventSourcingSystem.dispatch(new MyCommand(PAYLOAD_1));
-
- assertThat(subscriber.getData()).containsExactly(PAYLOAD_1);
- }
-
- @Test
- default void throwingStoreShouldNotLeadToPublishing() {
- EventStore eventStore = mock(EventStore.class);
- doThrow(new RuntimeException()).when(eventStore).appendAll(anyScalaList());
- when(eventStore.getEventsOfAggregate(any())).thenReturn(History.empty());
-
- DataCollectorSubscriber subscriber = new DataCollectorSubscriber();
- EventSourcingSystem eventSourcingSystem = EventSourcingSystem.fromJava(
- ImmutableSet.of(simpleDispatcher(eventStore)),
- ImmutableSet.of(
- events -> {
- throw new RuntimeException();
- },
- subscriber),
- eventStore);
-
- assertThatThrownBy(() -> eventSourcingSystem.dispatch(new MyCommand(PAYLOAD_1)))
- .isInstanceOf(RuntimeException.class);
-
- assertThat(subscriber.getData()).isEmpty();
- }
-
- @Test
- default void dispatchShouldApplyCommandHandlerThenStoreGeneratedEvents(EventStore eventStore) {
- DataCollectorSubscriber subscriber = new DataCollectorSubscriber();
- EventSourcingSystem eventSourcingSystem = EventSourcingSystem.fromJava(
- ImmutableSet.of(simpleDispatcher(eventStore)),
- ImmutableSet.of(subscriber),
- eventStore);
-
- eventSourcingSystem.dispatch(new MyCommand(PAYLOAD_1));
-
- TestEvent expectedEvent = new TestEvent(EventId.first(), AGGREGATE_ID, PAYLOAD_1);
- assertThat(CollectionConverters.asJava(eventStore.getEventsOfAggregate(AGGREGATE_ID).getEvents()))
- .containsOnly(expectedEvent);
- }
-
- @Test
- default void dispatchShouldCallSubscriberForSubsequentCommands(EventStore eventStore) {
- DataCollectorSubscriber subscriber = new DataCollectorSubscriber();
- EventSourcingSystem eventSourcingSystem = EventSourcingSystem.fromJava(
- ImmutableSet.of(simpleDispatcher(eventStore)),
- ImmutableSet.of(subscriber),
- eventStore);
-
- eventSourcingSystem.dispatch(new MyCommand(PAYLOAD_1));
- eventSourcingSystem.dispatch(new MyCommand(PAYLOAD_2));
-
- assertThat(subscriber.getData()).containsExactly(PAYLOAD_1, PAYLOAD_2);
- }
-
- @Test
- default void dispatchShouldStoreEventsForSubsequentCommands(EventStore eventStore) {
- DataCollectorSubscriber subscriber = new DataCollectorSubscriber();
- EventSourcingSystem eventSourcingSystem = EventSourcingSystem.fromJava(
- ImmutableSet.of(simpleDispatcher(eventStore)),
- ImmutableSet.of(subscriber),
- eventStore);
-
- eventSourcingSystem.dispatch(new MyCommand(PAYLOAD_1));
- eventSourcingSystem.dispatch(new MyCommand(PAYLOAD_2));
-
- TestEvent expectedEvent1 = new TestEvent(EventId.first(), AGGREGATE_ID, PAYLOAD_1);
- TestEvent expectedEvent2 = new TestEvent(expectedEvent1.eventId().next(), AGGREGATE_ID, PAYLOAD_2);
- assertThat(CollectionConverters.asJava(eventStore.getEventsOfAggregate(AGGREGATE_ID).getEvents()))
- .containsOnly(expectedEvent1, expectedEvent2);
- }
-
- @Test
- default void dispatcherShouldBeAbleToReturnSeveralEvents(EventStore eventStore) {
- DataCollectorSubscriber subscriber = new DataCollectorSubscriber();
- EventSourcingSystem eventSourcingSystem = EventSourcingSystem.fromJava(
- ImmutableSet.of(wordCuttingDispatcher(eventStore)),
- ImmutableSet.of(subscriber),
- eventStore);
-
- eventSourcingSystem.dispatch(new MyCommand("This is a test"));
-
- assertThat(subscriber.getData()).containsExactly("This", "is", "a", "test");
- }
-
- @Test
- default void unknownCommandsShouldBeIgnored(EventStore eventStore) {
- DataCollectorSubscriber subscriber = new DataCollectorSubscriber();
- EventSourcingSystem eventSourcingSystem = EventSourcingSystem.fromJava(
- ImmutableSet.of(wordCuttingDispatcher(eventStore)),
- ImmutableSet.of(subscriber),
- eventStore);
-
- assertThatThrownBy(() -> eventSourcingSystem.dispatch(new Command() {
- }))
- .isInstanceOf(CommandDispatcher.UnknownCommandException.class);
- }
-
- @Test
- default void constructorShouldThrowWhenSeveralHandlersForTheSameCommand(EventStore eventStore) {
- DataCollectorSubscriber subscriber = new DataCollectorSubscriber();
-
- assertThatThrownBy(() ->
- EventSourcingSystem.fromJava(
- ImmutableSet.of(wordCuttingDispatcher(eventStore),
- simpleDispatcher(eventStore)),
- ImmutableSet.of(subscriber),
- eventStore))
- .isInstanceOf(IllegalArgumentException.class);
- }
-
- default CommandHandler<MyCommand> simpleDispatcher(EventStore eventStore) {
- return new CommandHandler<MyCommand>() {
- @Override
- public Class<MyCommand> handledClass() {
- return MyCommand.class;
- }
-
- @Override
- public scala.collection.immutable.List<? extends Event> handle(MyCommand myCommand) {
- History history = eventStore.getEventsOfAggregate(AGGREGATE_ID);
-
- return CollectionConverters.asScala(ImmutableList.of(new TestEvent(
- history.getNextEventId(),
- AGGREGATE_ID,
- myCommand.getPayload()))).toList();
- }
- };
- }
-
- default CommandHandler<MyCommand> wordCuttingDispatcher(EventStore eventStore) {
- return new CommandHandler<MyCommand>() {
- @Override
- public Class<MyCommand> handledClass() {
- return MyCommand.class;
- }
-
- @Override
- public scala.collection.immutable.List<? extends Event> handle(MyCommand myCommand) {
- History history = eventStore.getEventsOfAggregate(AGGREGATE_ID);
-
- EventIdIncrementer eventIdIncrementer = new EventIdIncrementer(history.getNextEventId());
-
- return CollectionConverters.asScala(Splitter.on(" ")
- .splitToList(myCommand.getPayload())
- .stream()
- .map(word -> new TestEvent(
- eventIdIncrementer.next(),
- AGGREGATE_ID,
- word))
- .collect(Guavate.toImmutableList())).toList();
- }
- };
- }
-
- class EventIdIncrementer {
- private EventId currentEventId;
-
- public EventIdIncrementer(EventId base) {
- this.currentEventId = base;
- }
-
- public EventId next() {
- currentEventId = currentEventId.next();
- return currentEventId;
- }
- }
-
- static <T> List<T> anyScalaList() {
- ThreadSafeMockingProgress.mockingProgress().getArgumentMatcherStorage().reportMatcher(new InstanceOf(scala.collection.immutable.List.class, "<any scala List>"));
- return scala.collection.immutable.List.<T>newBuilder().result();
- }
-
-}
\ No newline at end of file
diff --git a/event-sourcing/event-sourcing-core/src/test/scala/org/apache/james/eventsourcing/EventSourcingSystemTest.scala b/event-sourcing/event-sourcing-core/src/test/scala/org/apache/james/eventsourcing/EventSourcingSystemTest.scala
new file mode 100644
index 0000000..641d98a
--- /dev/null
+++ b/event-sourcing/event-sourcing-core/src/test/scala/org/apache/james/eventsourcing/EventSourcingSystemTest.scala
@@ -0,0 +1,167 @@
+ /***************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+package org.apache.james.eventsourcing
+
+import com.google.common.base.Splitter
+import org.apache.james.eventsourcing.eventstore.{EventStore, History}
+import org.assertj.core.api.Assertions.{assertThat, assertThatThrownBy}
+import org.junit.jupiter.api.Test
+import org.mockito.ArgumentMatchers.any
+import org.mockito.Mockito.{doThrow, mock, when}
+import org.mockito.internal.matchers.InstanceOf
+import org.mockito.internal.progress.ThreadSafeMockingProgress
+
+import scala.collection.immutable.List
+import scala.jdk.CollectionConverters._
+
+object EventSourcingSystemTest {
+ val PAYLOAD_1 = "payload1"
+ val PAYLOAD_2 = "payload2"
+ val AGGREGATE_ID = TestAggregateId(42)
+
+ class MyCommand(val payload: String) extends Command {
+ def getPayload: String = payload
+ }
+
+ class EventIdIncrementer(var currentEventId: EventId) {
+ def next: EventId = {
+ currentEventId = currentEventId.next
+ currentEventId
+ }
+ }
+
+ def anyScalaList[T] : List[T] = {
+ ThreadSafeMockingProgress.mockingProgress
+ .getArgumentMatcherStorage
+ .reportMatcher(new InstanceOf(classOf[List[_]], "<any scala List>"))
+ scala.collection.immutable.List.newBuilder[T].result
+ }
+}
+
+trait EventSourcingSystemTest {
+ @Test
+ def dispatchShouldApplyCommandHandlerThenCallSubscribers(eventStore: EventStore) : Unit = {
+ val subscriber = new DataCollectorSubscriber
+ val eventSourcingSystem = new EventSourcingSystem(Set(simpleDispatcher(eventStore)), Set(subscriber), eventStore)
+ eventSourcingSystem.dispatch(new EventSourcingSystemTest.MyCommand(EventSourcingSystemTest.PAYLOAD_1))
+ assertThat(subscriber.getData.asJava).containsExactly(EventSourcingSystemTest.PAYLOAD_1)
+ }
+
+ @Test
+ def throwingSubscribersShouldNotAbortSubscriberChain(eventStore: EventStore) : Unit = {
+ val subscriber = new DataCollectorSubscriber
+ val eventSourcingSystem = new EventSourcingSystem(
+ Set(simpleDispatcher(eventStore)),
+ Set((_: Event) => throw new RuntimeException, subscriber),
+ eventStore)
+ eventSourcingSystem.dispatch(new EventSourcingSystemTest.MyCommand(EventSourcingSystemTest.PAYLOAD_1))
+ assertThat(subscriber.getData.asJava).containsExactly(EventSourcingSystemTest.PAYLOAD_1)
+ }
+
+ @Test
+ def throwingStoreShouldNotLeadToPublishing() : Unit = {
+ val eventStore = mock(classOf[EventStore])
+ doThrow(new RuntimeException).when(eventStore).appendAll(EventSourcingSystemTest.anyScalaList)
+ when(eventStore.getEventsOfAggregate(any)).thenReturn(History.empty)
+ val subscriber = new DataCollectorSubscriber
+ val eventSourcingSystem = new EventSourcingSystem(
+ Set(simpleDispatcher(eventStore)),
+ Set((_: Event) => throw new RuntimeException, subscriber),
+ eventStore)
+ assertThatThrownBy(() => eventSourcingSystem.dispatch(new EventSourcingSystemTest.MyCommand(EventSourcingSystemTest.PAYLOAD_1)))
+ .isInstanceOf(classOf[RuntimeException])
+ assertThat(subscriber.getData.asJava).isEmpty()
+ }
+
+ @Test
+ def dispatchShouldApplyCommandHandlerThenStoreGeneratedEvents(eventStore: EventStore) : Unit = {
+ val subscriber = new DataCollectorSubscriber
+ val eventSourcingSystem = new EventSourcingSystem(Set(simpleDispatcher(eventStore)), Set(subscriber), eventStore)
+ eventSourcingSystem.dispatch(new EventSourcingSystemTest.MyCommand(EventSourcingSystemTest.PAYLOAD_1))
+ val expectedEvent = TestEvent(EventId.first, EventSourcingSystemTest.AGGREGATE_ID, EventSourcingSystemTest.PAYLOAD_1)
+ assertThat(eventStore.getEventsOfAggregate(EventSourcingSystemTest.AGGREGATE_ID).getEvents.asJava).containsOnly(expectedEvent)
+ }
+
+ @Test
+ def dispatchShouldCallSubscriberForSubsequentCommands(eventStore: EventStore) : Unit = {
+ val subscriber = new DataCollectorSubscriber
+ val eventSourcingSystem = new EventSourcingSystem(Set(simpleDispatcher(eventStore)), Set(subscriber), eventStore)
+ eventSourcingSystem.dispatch(new EventSourcingSystemTest.MyCommand(EventSourcingSystemTest.PAYLOAD_1))
+ eventSourcingSystem.dispatch(new EventSourcingSystemTest.MyCommand(EventSourcingSystemTest.PAYLOAD_2))
+ assertThat(subscriber.getData.asJava).containsExactly(EventSourcingSystemTest.PAYLOAD_1, EventSourcingSystemTest.PAYLOAD_2)
+ }
+
+ @Test
+ def dispatchShouldStoreEventsForSubsequentCommands(eventStore: EventStore) : Unit = {
+ val subscriber = new DataCollectorSubscriber
+ val eventSourcingSystem = new EventSourcingSystem(Set(simpleDispatcher(eventStore)), Set(subscriber), eventStore)
+ eventSourcingSystem.dispatch(new EventSourcingSystemTest.MyCommand(EventSourcingSystemTest.PAYLOAD_1))
+ eventSourcingSystem.dispatch(new EventSourcingSystemTest.MyCommand(EventSourcingSystemTest.PAYLOAD_2))
+ val expectedEvent1 = TestEvent(EventId.first, EventSourcingSystemTest.AGGREGATE_ID, EventSourcingSystemTest.PAYLOAD_1)
+ val expectedEvent2 = TestEvent(expectedEvent1.eventId.next, EventSourcingSystemTest.AGGREGATE_ID, EventSourcingSystemTest.PAYLOAD_2)
+ assertThat(eventStore.getEventsOfAggregate(EventSourcingSystemTest.AGGREGATE_ID).getEvents.asJava).containsOnly(expectedEvent1, expectedEvent2)
+ }
+
+ @Test
+ def dispatcherShouldBeAbleToReturnSeveralEvents(eventStore: EventStore) : Unit = {
+ val subscriber = new DataCollectorSubscriber
+ val eventSourcingSystem = new EventSourcingSystem(Set(wordCuttingDispatcher(eventStore)), Set(subscriber), eventStore)
+ eventSourcingSystem.dispatch(new EventSourcingSystemTest.MyCommand("This is a test"))
+ assertThat(subscriber.getData.asJava).containsExactly("This", "is", "a", "test")
+ }
+
+ @Test
+ def unknownCommandsShouldBeIgnored(eventStore: EventStore) : Unit = {
+ val subscriber = new DataCollectorSubscriber
+ val eventSourcingSystem = new EventSourcingSystem(Set(wordCuttingDispatcher(eventStore)), Set(subscriber), eventStore)
+ assertThatThrownBy(() => eventSourcingSystem.dispatch(new Command() {}))
+ .isInstanceOf(classOf[CommandDispatcher.UnknownCommandException])
+ }
+
+ @Test
+ def constructorShouldThrowWhenSeveralHandlersForTheSameCommand(eventStore: EventStore) : Unit = {
+ val subscriber = new DataCollectorSubscriber
+ assertThatThrownBy(() => new EventSourcingSystem(
+ Set(wordCuttingDispatcher(eventStore), simpleDispatcher(eventStore)),
+ Set(subscriber), eventStore))
+ .isInstanceOf(classOf[IllegalArgumentException])
+ }
+
+ def simpleDispatcher(eventStore: EventStore) = new CommandHandler[EventSourcingSystemTest.MyCommand]() {
+ override def handledClass: Class[EventSourcingSystemTest.MyCommand] = classOf[EventSourcingSystemTest.MyCommand]
+
+ override def handle(myCommand: EventSourcingSystemTest.MyCommand): List[TestEvent] = {
+ val history = eventStore.getEventsOfAggregate(EventSourcingSystemTest.AGGREGATE_ID)
+ List(TestEvent(history.getNextEventId, EventSourcingSystemTest.AGGREGATE_ID, myCommand.getPayload))
+ }
+ }
+
+ def wordCuttingDispatcher(eventStore: EventStore) = new CommandHandler[EventSourcingSystemTest.MyCommand]() {
+ override def handledClass: Class[EventSourcingSystemTest.MyCommand] = classOf[EventSourcingSystemTest.MyCommand]
+
+ override def handle(myCommand: EventSourcingSystemTest.MyCommand): List[TestEvent] = {
+ val history = eventStore.getEventsOfAggregate(EventSourcingSystemTest.AGGREGATE_ID)
+ val eventIdIncrementer = new EventSourcingSystemTest.EventIdIncrementer(history.getNextEventId)
+ Splitter.on(" ").splitToList(myCommand.getPayload)
+ .asScala
+ .toList
+ .map((word: String) => TestEvent(eventIdIncrementer.next, EventSourcingSystemTest.AGGREGATE_ID, word))
+ }
+ }
+}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org