I have a test for particular actor. This actor depends on some other actors, so I use TestProbe() to test in isolation.
My problem is, that I receive more messages then I am interested in testing at this very particular test. For example:
val a = TestProbe()
val b = TestProbe()
val actor = TestActorRef(new MyActor(a.ref, b.ref))
actor ! Message(1, 2)
b.expectMsg(3)
The test fails, because while creating MyActor it sends some kind of "registration" message to ones passed in constructor.
The message 3 arrives eventually, but assertion fails - this is not the first message to arrive.
I would like to avoid asserting more messages than I need for a test - those can change, etc, it is not the scope of a particular test anyway.
As the TestProbe does not contain such methods - I suspect there may be something wrong with my test setup (or rather my project architecture then). I see there are many methods like fishForMessage but all those require a explicit time parameters which seems like irrelevant as my whole test is purely synchronous.
Is there any way to accomplish such test is desired message is just among all the were received? If not, how can my setup can be improved to be easy testable?
The fishForMessage actually fits. All these assertions including expectMsg are asynchronous. expectMsg just uses the preconfigured timeFactor as timeout.
TestActorRef guarantees you only that CallingThreadDispatcher will be used to send messages and execute futures (if they use dispatcher from the test actor), so they will act sequentially til they're use context.dispatcher. Nothing stops some code inside your MyActor from using another dispatcher to send a response, so all checks still should be asynchronous - you just can't get rid of that.
Related
I am trying to configure an Akka Actor for Cluster Sharding, one thing that I am not quite sure, is it possible to configure several Stop Messages for an Entity for graceful Shutdown.
for ex, Entity configuration like following will trigger graceful shutdown for both 'onDelete' and 'onExit' or it will do it only for 'onExit'?
sharding
.init(
Entity(Actor1Key) {
context => ....
}
)
.withStopMessage(Actor1.onDelete)
.withStopMessage(Actor1.onExit)
if not do you have any idea how I can achieve this Behaviour?
Thx for answers
I think there may some confusion around what the purpose of the stopMessage is. There should not be a need for multiple stop messages.
The stopMessage sent by sharding after passivation has been requested by the actor, which is done by sending Passivate from the sharded actor itself.
You can let any of the messages that the actor accepts trigger passivation, the shard will send back the stopMessage when it is safe for the actor to actually stop.
The reason you should passivate rather than just Behaviors.stopped the actor is that there may be messages that was en route to the actor (mailbox and I think possibly a buffer in the shard in some circumstances) before the message causing it deciding to stop and you want to process those first. Passivation allows for that to happen by including a roundtrip to the shard actor which is charge of routing messages to the sharded actor.
A bit more details in the docs here: https://doc.akka.io/docs/akka/current/typed/cluster-sharding.html#passivation
What you have specified would only trigger the stop message for Actor1.onExit. The reason is how a stop message is defined for an Entity:
val stopMessage: Optional[M],
So you see that this is a plain optional thus no multiple elements are possible. You can also check how the withStopMessage is implemented here:
def withStopMessage(newStopMessage: M): Entity[M, E] =
copy(stopMessage = Optional.ofNullable(newStopMessage))
So you are basically going to "overwrite" the message any time you call withStopMessage. Unfortunately, I am not aware of any other way of specifying multiple stop messages (besides combining multiple messages in a common trait but I think this is not what you are looking for).
By the definition of CQRS command can/should be validated and at the end even declined (if validation does not pass). As a part of my command validation I check if state transition is really needed. So let take a simple, dummy example: actor is in state A. A command is send to actor to transit to state B. The command gets validated and at the end event is generated StateBUpdated. Then the exact same command is send to transit to state B. Again command gets validated and during the validation it is decided that no event will be generated (since we are already in state B) and just respond back that command was processed and everything is ok. It is kind of idempotency thingy.
Nevertheless, I have hard time (unit) testing this. Usual unit test for persistent actor looks like sending a command to the actor and then restarting actor and check that state is persisted. I want to test if I send a command to the actor to check how many events were generated. How to do that?
Thanks
We faced this problem while developing our internal CQRS framework based on akka persistence. Our solution was to use Persistence Query(https://doc.akka.io/docs/akka/2.5/scala/persistence-query.html). In case you haven't used it, it is a query interface that journal plugins can optionally implement, and can be used as the read side in a CQRS system.
For your testing purposes, the method would be eventsByPersistenceId, which will give you an akka streams Source with all the events persisted by an actor. The source can be folded into a list of events like:
public CompletableFuture<List<Message<?>>> getEventsForIdAsync(String id, FiniteDuration readTimeout) {
return ((EventsByPersistenceIdQuery)readJournal).eventsByPersistenceId(id, 0L, Long.MAX_VALUE)
.takeWithin(readTimeout)
.map(eventEnvelope -> (Message<?>)eventEnvelope.event())
.<List<Message<?>>>runFold(
new ArrayList<Message<?>>(),
(list, event) -> {
list.add(event);
return list;
}, materializer)
.toCompletableFuture();
}
Sorry if the above seems bloated, we use Java, so if you are used to Scala it is indeed ugly. Getting the readJournal is as easy as:
ReadJournal readJournal = PersistenceQuery.lookup().get(actorSystem)
.getReadJournalFor(InMemoryReadJournal.class, InMemoryReadJournal.Identifier())
You can see that we use the akka.persistence.inmemory plugin since it is the best for testing, but any plugin which implements the Persistence Query API would work.
We actually made a BDD-like test API inside our framework, so a typical test looks like this:
fixture
.given("ID1", event(new AccountCreated("ID1", "John Smith")))
.when(command(new AddAmount("ID1", 2.0)))
.then("ID1", eventApplied(new AmountAdded("ID1", 2.0)))
.test();
As you see, we also handle the case of setting up previous events in the given clause as well a potentially dealing with multiple persistenceIds(we use ClusterSharding).
From you description it sounds like you need either to mock your persistence, or at lest be able to access it's state easily. I was able to find two projects that will do that:
akka-persistence-mock which is designed for use in testing, but not actively developed.
akka-persistence-inmemory
which is very useful when testing persistent actors, persistent FSM and akka cluster.
I would recommend the latter, since it provides the possibility of retrieving all messages from the journal.
is there any way to wait till all messages in mailboxes(and stashes) are processed in whole ActorSystem?
I'm trying to develop architecture of integration tests for system based on Akka. And it would be convenient to have method something like actorSystem.awaitAllWorkDone(), in this case arbitrary test would look like:
Start whole environment consisting of many actors
Send message triggering functionality being tested
Call actorSystem.awaitAllWorkDone(). Which waits till all messages are processed, including message sent from step 2 and all inner communication messages which it causes. For example message from step 2 fires 10 other messages sent to other actors, so it should wait for them too.
Now the system in "consistent" state and I can verify it's state. Like verify that all required changes were made in db or all required side-effects were made.
Actually, step 3 can be replaced with waiting for message specific for this test which indicates that all inner-communication are completed. But whole point is to have one "await" method for any test case, and not to searching which message for this test case is indicator that all inner-communication are completed.
Anybody have an idea how to achieve this?
Java/Akka (v2.3.9) here. Each of my Akka UntypedActor subclasses has the ability to respond to several "generic" messages, such as ExecuteOrder66:
// Groovy pseudo-code
class StormTrooper extends UntypedActor {
#Override
void onReceive(Object message) throws Exception {
if(message instanceof ExecuteOrder66) {
// Betray the Jedi, serve only the emperor.
}
}
}
Let's say I have 100 different actor subclasses that each support ExecuteOrder66. I need a way to broadcast instances of this message to every single one of my actors; so like a public broadcast announce which everybody gets.
I think that link to the Akka docs above gets me close, but I'm not seeing one that sends an ExecuteOrder66 to every single one of my actors. Any ideas?
The problem is that it is not quite clear who "everybody" is. What if some actor a gets a handshake message from some other actor b from remote actor system, stores b's reference, exchanges a few messages, then fails and restarts without the reference of b? Is b part of "everybody"? Who is responsible for finding the actor b again? How is one even supposed to know that b is still alive?
However, if you have a single specific actor system, a path selection with wildcards could do what you want. Something like this might do the job:
mySystem.actorSelection("akka://mySystemName/**")
This actor selection can then be used to tell (!) your broadcasted message to every actor on the system. You might also consider to be a little more restrictive, and select only the actors under /user, without touching the system actors.
Disclaimer: a little ad-hoc actor system I've just set up in the REPL doesn't complain about the path as indicated above, but I did not test it thoroughly. A runnable toy-example might be helpful.
In Practical Object-Oriented Design in Ruby: An Agile Primer, the author writes, "[An object] is responsible for testing its own interface and it does so by making assertions about the results that these [incoming] messages return. … These messages need tests because other application objects dpeend on their signatures and the results they return."
She explains that "the first requirement for testing an incoming message is to prove that it returns the correct value in every possible situation," giving this as an example unit test for the diameter method for a hypothetical Wheel class:
def test_calculates_diameter
wheel = Wheel.new(26, 1.5)
assert_in_delta(29, wheel.diameter, 0.01)
end
My question is, what about incoming messages that don't return a value? I have an object whose public interface only has two methods that don't return a value but merely change the state of the receiving object. Do I still need to test that object? and, if so, how?
In typing the question, I think I've realized the answer: to use the author's nomenclature, I should test the outgoing "command" messages that are sent in response to the incoming messages.
For some context, the author later writes, "Many outgoing messages do have side effects (… an action is taken by an observer) upon which your application depends. These messages are commands and it is the respondibility of sending object to prove that they are properly sent."
In my case, my object is a container that sends messages to its children when its state changes, so that object's test should ensure that those messages are sent to its children.