improvements of the PersistenceTestKit doc samples

* and actually run the tests
This commit is contained in:
Patrik Nordwall 2020-03-25 12:52:05 +01:00
parent abbef000ab
commit 5ac480199a
5 changed files with 235 additions and 187 deletions

View file

@ -107,10 +107,10 @@ Java
A typical scenario is to create a persistent actor, send commands to it and check that it persists events as it is expected:
Scala
: @@snip [TestKitExamples.scala](/akka-docs/src/test/scala/docs/persistence/testkit/TestKitExamples.scala) { #testkit-typed-usecase }
: @@snip [TestKitExamples.scala](/akka-docs/src/test/scala/docs/persistence/testkit/TestKitExamples.scala) { #test }
Java
: @@snip [TestKitExamples.java](/akka-docs/src/test/java/jdocs/persistence/testkit/TestKitExamples.java) { #testkit-typed-usecase }
: @@snip [TestKitExamples.java](/akka-docs/src/test/java/jdocs/persistence/testkit/PersistenceTestKitSampleTest.java) { #test }
You can safely use persistence testkit in combination with main akka testkit.
@ -188,7 +188,7 @@ For tests that involve more than one Cluster node you have to use another journa
While it's possible to use the @ref:[Persistence Plugin Proxy](../persistence-plugins.md#persistence-plugin-proxy)
it's often better and more realistic to use a real database.
See [akka-samples issue #128](https://github.com/akka/akka-samples/issues/128).
The @ref:[CQRS example](../project/examples.md#cqrs) includes tests that are using Akka Persistence Cassandra.
### Plugin initialization

View file

@ -0,0 +1,125 @@
/*
* Copyright (C) 2009-2020 Lightbend Inc. <https://www.lightbend.com>
*/
package jdocs.persistence.testkit;
import akka.actor.testkit.typed.javadsl.TestKitJunitResource;
import akka.actor.typed.ActorRef;
import akka.actor.typed.Behavior;
import akka.actor.typed.javadsl.Behaviors;
import akka.persistence.testkit.PersistenceTestKitPlugin;
import akka.persistence.testkit.javadsl.PersistenceTestKit;
import akka.persistence.typed.PersistenceId;
import akka.persistence.typed.javadsl.CommandHandler;
import akka.persistence.typed.javadsl.EventHandler;
import akka.persistence.typed.javadsl.EventSourcedBehavior;
import akka.serialization.jackson.CborSerializable;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.typesafe.config.ConfigFactory;
import jdocs.AbstractJavaTest;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
// #test
public class PersistenceTestKitSampleTest extends AbstractJavaTest {
@ClassRule
public static final TestKitJunitResource testKit =
new TestKitJunitResource(
PersistenceTestKitPlugin.getInstance()
.config()
.withFallback(ConfigFactory.defaultApplication()));
PersistenceTestKit persistenceTestKit = PersistenceTestKit.create(testKit.system());
@Before
public void beforeEach() {
persistenceTestKit.clearAll();
}
@Test
public void test() {
PersistenceId persistenceId = PersistenceId.ofUniqueId("some-id");
ActorRef<YourPersistentBehavior.Cmd> ref =
testKit.spawn(YourPersistentBehavior.create(persistenceId));
YourPersistentBehavior.Cmd cmd = new YourPersistentBehavior.Cmd("data");
ref.tell(cmd);
YourPersistentBehavior.Evt expectedEventPersisted = new YourPersistentBehavior.Evt(cmd.data);
persistenceTestKit.expectNextPersisted(persistenceId.id(), expectedEventPersisted);
}
}
class YourPersistentBehavior
extends EventSourcedBehavior<
YourPersistentBehavior.Cmd, YourPersistentBehavior.Evt, YourPersistentBehavior.State> {
static final class Cmd implements CborSerializable {
public final String data;
@JsonCreator
public Cmd(String data) {
this.data = data;
}
}
static final class Evt implements CborSerializable {
public final String data;
@JsonCreator
public Evt(String data) {
this.data = data;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Evt evt = (Evt) o;
return data.equals(evt.data);
}
@Override
public int hashCode() {
return data.hashCode();
}
}
static final class State implements CborSerializable {}
static Behavior<Cmd> create(PersistenceId persistenceId) {
return Behaviors.setup(context -> new YourPersistentBehavior(persistenceId));
}
private YourPersistentBehavior(PersistenceId persistenceId) {
super(persistenceId);
}
@Override
public State emptyState() {
// some state
return new State();
}
@Override
public CommandHandler<Cmd, Evt, State> commandHandler() {
return newCommandHandlerBuilder()
.forAnyState()
.onCommand(Cmd.class, command -> Effect().persist(new Evt(command.data)))
.build();
}
@Override
public EventHandler<State, Evt> eventHandler() {
// TODO handle events
return newEventHandlerBuilder().forAnyState().onEvent(Evt.class, (state, evt) -> state).build();
}
}
// #test

View file

@ -4,13 +4,10 @@
package jdocs.persistence.testkit;
import akka.actor.testkit.typed.javadsl.TestKitJunitResource;
import akka.actor.typed.ActorRef;
import akka.persistence.testkit.DeleteEvents;
import akka.persistence.testkit.DeleteSnapshotByMeta;
import akka.persistence.testkit.DeleteSnapshotsByCriteria;
import akka.persistence.testkit.JournalOperation;
import akka.persistence.testkit.PersistenceTestKitPlugin;
import akka.persistence.testkit.ProcessingPolicy;
import akka.persistence.testkit.ProcessingResult;
import akka.persistence.testkit.ProcessingSuccess;
@ -22,15 +19,6 @@ import akka.persistence.testkit.SnapshotOperation;
import akka.persistence.testkit.StorageFailure;
import akka.persistence.testkit.WriteEvents;
import akka.persistence.testkit.WriteSnapshot;
import akka.persistence.testkit.javadsl.PersistenceTestKit;
import akka.persistence.typed.PersistenceId;
import akka.persistence.typed.javadsl.CommandHandler;
import akka.persistence.typed.javadsl.EventHandler;
import akka.persistence.typed.javadsl.EventSourcedBehavior;
import com.typesafe.config.ConfigFactory;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
public class TestKitExamples {
@ -105,81 +93,3 @@ public class TestKitExamples {
// #set-snapshot-storage-policy
}
// #testkit-typed-usecase
class SampleTest {
@ClassRule
public static final TestKitJunitResource testKit =
new TestKitJunitResource(
PersistenceTestKitPlugin.getInstance()
.config()
.withFallback(ConfigFactory.defaultApplication()));
PersistenceTestKit persistenceTestKit = PersistenceTestKit.create(testKit.system());
@Before
void beforeAll() {
persistenceTestKit.clearAll();
}
@Test
void test() {
ActorRef<Cmd> ref =
testKit.spawn(new YourPersistentBehavior(PersistenceId.ofUniqueId("some-id")));
Cmd cmd = new Cmd("data");
ref.tell(cmd);
Evt expectedEventPersisted = new Evt(cmd.data);
persistenceTestKit.expectNextPersisted("your-persistence-id", expectedEventPersisted);
}
}
final class Cmd {
public final String data;
public Cmd(String data) {
this.data = data;
}
}
final class Evt {
public final String data;
public Evt(String data) {
this.data = data;
}
}
final class State {}
class YourPersistentBehavior extends EventSourcedBehavior<Cmd, Evt, State> {
public YourPersistentBehavior(PersistenceId persistenceId) {
super(persistenceId);
}
@Override
public State emptyState() {
// some state
return new State();
}
@Override
public CommandHandler<Cmd, Evt, State> commandHandler() {
return newCommandHandlerBuilder()
.forAnyState()
.onCommand(Cmd.class, command -> Effect().persist(new Evt(command.data)))
.build();
}
@Override
public EventHandler<State, Evt> eventHandler() {
// TODO handle events
return newEventHandlerBuilder().build();
}
}
// #testkit-typed-usecase

View file

@ -4,51 +4,69 @@
package docs.persistence.testkit
import akka.actor.typed.ActorSystem
import akka.persistence.testkit._
import akka.persistence.testkit.scaladsl.PersistenceTestKit
import akka.persistence.typed.scaladsl.{ Effect, EventSourcedBehavior }
import akka.persistence.typed.PersistenceId
import akka.persistence.typed.scaladsl.Effect
import akka.persistence.typed.scaladsl.EventSourcedBehavior
import akka.serialization.jackson.CborSerializable
import com.typesafe.config.ConfigFactory
import org.scalatest.BeforeAndAfterAll
import docs.persistence.testkit.PersistenceTestKitSampleSpec._
import org.scalatest.BeforeAndAfterEach
import org.scalatest.wordspec.AnyWordSpecLike
class TestKitExamples {
object PersistenceTestKitSampleSpec {
final case class Cmd(data: String) extends CborSerializable
final case class Evt(data: String) extends CborSerializable
object State {
val empty: State = new State
}
final class State extends CborSerializable {
def updated(event: Evt): State = this
}
}
//#testkit-typed-usecase
class TypedSampleSpec extends AnyWordSpecLike with BeforeAndAfterAll {
//#test
import akka.actor.testkit.typed.scaladsl.ScalaTestWithActorTestKit
import akka.persistence.testkit.PersistenceTestKitPlugin
import akka.persistence.testkit.scaladsl.PersistenceTestKit
class PersistenceTestKitSampleSpec
extends ScalaTestWithActorTestKit(PersistenceTestKitPlugin.config.withFallback(ConfigFactory.defaultApplication()))
with AnyWordSpecLike
with BeforeAndAfterEach {
val system: ActorSystem[Cmd] = ActorSystem(
EventSourcedBehavior[Cmd, Evt, State](
persistenceId = ???,
eventHandler = ???,
commandHandler = (_, cmd) => Effect.persist(Evt(cmd.data)),
emptyState = ???),
"name",
PersistenceTestKitPlugin.config.withFallback(ConfigFactory.defaultApplication()))
val persistenceTestKit = PersistenceTestKit(system)
override def beforeAll(): Unit =
override def beforeEach(): Unit = {
persistenceTestKit.clearAll()
}
"Persistent actor" should {
"persist all events" in {
val persistentActor = system
val persistenceId = PersistenceId.ofUniqueId("your-persistence-id")
val persistentActor = spawn(
EventSourcedBehavior[Cmd, Evt, State](
persistenceId,
emptyState = State.empty,
commandHandler = (_, cmd) => Effect.persist(Evt(cmd.data)),
eventHandler = (state, evt) => state.updated(evt)))
val cmd = Cmd("data")
persistentActor ! cmd
val expectedPersistedEvent = Evt(cmd.data)
persistenceTestKit.expectNextPersisted("your-persistence-id", expectedPersistedEvent)
persistenceTestKit.expectNextPersisted(persistenceId.id, expectedPersistedEvent)
}
}
}
//#testkit-typed-usecase
}
//#test
//#set-event-storage-policy
class SampleEventStoragePolicy extends EventStorage.JournalPolicies.PolicyType {
//#set-event-storage-policy
import akka.persistence.testkit._
class SampleEventStoragePolicy extends EventStorage.JournalPolicies.PolicyType {
//you can use internal state, it does not need to be thread safe
var count = 1
@ -70,11 +88,11 @@ class TestKitExamples {
ProcessingSuccess
}
}
//#set-event-storage-policy
}
//#set-event-storage-policy
//#set-snapshot-storage-policy
class SampleSnapshotStoragePolicy extends SnapshotStorage.SnapshotPolicies.PolicyType {
//#set-snapshot-storage-policy
class SampleSnapshotStoragePolicy extends SnapshotStorage.SnapshotPolicies.PolicyType {
//you can use internal state, it does not need to be thread safe
var count = 1
@ -97,11 +115,5 @@ class TestKitExamples {
} else {
ProcessingSuccess
}
}
//#set-snapshot-storage-policy
}
case class Cmd(data: String)
case class Evt(data: String)
trait State
//#set-snapshot-storage-policy

View file

@ -201,6 +201,7 @@ lazy val docs = akkaModule("akka-docs")
.settings(Dependencies.docs)
.settings(Paradox.settings)
.settings(ParadoxSupport.paradoxWithCustomDirectives)
.settings(javacOptions += "-parameters") // for Jackson
.enablePlugins(
AkkaParadoxPlugin,
DeployRsync,