Improving docs- removing redundant phrases (#29744)

* Improving docs- removing redundant phrases

* Apply suggestions from code review

Co-authored-by: Arnout Engelen <github@bzzt.net>

* Making changes to improve docs

Co-authored-by: Arnout Engelen <github@bzzt.net>
This commit is contained in:
Muskan Gupta 2020-10-21 12:57:31 +05:30 committed by GitHub
parent 432d94d5a4
commit b705ded314
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 79 additions and 90 deletions

View file

@ -12,7 +12,7 @@ Streams the elements through the given future flow once it successfully complete
## Description ## Description
Streams the elements through the given flow once the `CompletionStage` successfully completes. Streams the elements through the given flow once the `CompletionStage` successfully completes.
If the future fails the stream is failed. If the future fails the stream fails.
## Examples ## Examples

View file

@ -34,10 +34,10 @@ causes (i.e. exceptions) into one of the four choices given above; notably,
this function does not take the failed actors identity as an input. It is this function does not take the failed actors identity as an input. It is
quite easy to come up with examples of structures where this might not seem quite easy to come up with examples of structures where this might not seem
flexible enough, e.g. wishing for different strategies to be applied to flexible enough, e.g. wishing for different strategies to be applied to
different subordinates. At this point it is vital to understand that different subordinates. At this point, it is vital to understand that
supervision is about forming a recursive fault handling structure. If you try supervision is about forming a recursive fault handling structure. If you try
to do too much at one level, it will become hard to reason about, hence the to do too much at one level, it will become hard to reason about, hence the
recommended way in this case is to add a level of supervision. recommended way, in this case, is to add a level of supervision.
Akka implements a specific form called “parental supervision”. Actors can only Akka implements a specific form called “parental supervision”. Actors can only
be created by other actors—where the top-level actor is provided by the be created by other actors—where the top-level actor is provided by the
@ -45,13 +45,13 @@ library—and each created actor is supervised by its parent. This restriction
makes the formation of actor supervision hierarchies implicit and encourages makes the formation of actor supervision hierarchies implicit and encourages
sound design decisions. It should be noted that this also guarantees that sound design decisions. It should be noted that this also guarantees that
actors cannot be orphaned or attached to supervisors from the outside, which actors cannot be orphaned or attached to supervisors from the outside, which
might otherwise catch them unawares. In addition, this yields a natural and might otherwise catch them unawares. Besides, this yields a natural and
clean shutdown procedure for (sub-trees of) actor applications. clean shutdown procedure for (sub-trees of) actor applications.
@@@ warning @@@ warning
Supervision related parent-child communication happens by special system Supervision-related communication happens by special system
messages that have their own mailboxes separate from user messages. This messages that have their mailboxes separate from user messages. This
implies that supervision related events are not deterministically implies that supervision related events are not deterministically
ordered relative to ordinary messages. In general, the user cannot influence ordered relative to ordinary messages. In general, the user cannot influence
the order of normal messages and failure notifications. For details and the order of normal messages and failure notifications. For details and
@ -85,11 +85,10 @@ will shut down the whole actor system.
### `/system`: The System Guardian ### `/system`: The System Guardian
This special guardian has been introduced in order to achieve an orderly This special guardian has been introduced to achieve an orderly
shut-down sequence where logging remains active while all normal actors shut-down sequence where logging remains active while all normal actors
terminate, even though logging itself is implemented using actors. This is terminate, even though logging itself is implemented using actors. This is
realized by having the system guardian watch the user guardian and initiate its own realized by having the system guardian watch the user guardian and initiate its shut-down upon reception of the `Terminated` message. The top-level
shut-down upon reception of the `Terminated` message. The top-level
system actors are supervised using a strategy which will restart indefinitely system actors are supervised using a strategy which will restart indefinitely
upon all types of `Exception` except for upon all types of `Exception` except for
`ActorInitializationException` and `ActorKilledException`, which `ActorInitializationException` and `ActorKilledException`, which
@ -128,7 +127,7 @@ children has such tight dependencies among them, that a failure of one child
affects the function of the others, i.e. they are inextricably linked. Since a affects the function of the others, i.e. they are inextricably linked. Since a
restart does not clear out the mailbox, it often is best to terminate the children restart does not clear out the mailbox, it often is best to terminate the children
upon failure and re-create them explicitly from the supervisor (by watching the upon failure and re-create them explicitly from the supervisor (by watching the
childrens lifecycle); otherwise you have to make sure that it is no problem childrens lifecycle); otherwise, you have to make sure that it is no problem
for any of the actors to receive a message which was queued before the restart for any of the actors to receive a message which was queued before the restart
but processed afterwards. but processed afterwards.
@ -137,7 +136,7 @@ automatically terminate the other children in an all-for-one strategy; this can
be done by watching their lifecycle: if the `Terminated` message be done by watching their lifecycle: if the `Terminated` message
is not handled by the supervisor, it will throw a `DeathPactException` is not handled by the supervisor, it will throw a `DeathPactException`
which (depending on its supervisor) will restart it, and the default which (depending on its supervisor) will restart it, and the default
`preRestart` action will terminate all children. Of course this can be `preRestart` action will terminate all children. Of course, this can be
handled explicitly as well. handled explicitly as well.
Please note that creating one-off actors from an all-for-one supervisor entails Please note that creating one-off actors from an all-for-one supervisor entails
@ -145,7 +144,3 @@ that failures escalated by the temporary actor will affect all the permanent
ones. If this is not desired, install an intermediate supervisor; this can very ones. If this is not desired, install an intermediate supervisor; this can very
be done by declaring a router of size 1 for the worker, see be done by declaring a router of size 1 for the worker, see
@ref:[Routing](routing.md). @ref:[Routing](routing.md).

View file

@ -22,7 +22,7 @@ To use Akka Testkit, you must add the following dependency in your project:
As with any piece of software, automated tests are a very important part of the As with any piece of software, automated tests are a very important part of the
development cycle. The actor model presents a different view on how units of development cycle. The actor model presents a different view on how units of
code are delimited and how they interact, which has an influence on how to code are delimited and how they interact, which influences how to
perform tests. perform tests.
Akka comes with a dedicated module `akka-testkit` for supporting tests. Akka comes with a dedicated module `akka-testkit` for supporting tests.
@ -57,12 +57,12 @@ assertions detailed below. @scala[When mixing in the trait `ImplicitSender` this
test actor is implicitly used as sender reference when dispatching messages test actor is implicitly used as sender reference when dispatching messages
from the test procedure.] @java[The test actors reference is obtained using the from the test procedure.] @java[The test actors reference is obtained using the
`getRef()` method as demonstrated above.] The `testActor` may also be passed to `getRef()` method as demonstrated above.] The `testActor` may also be passed to
other actors as usual, usually subscribing it as notification listener. There other actors, as usual, usually subscribing it as notification listener. There
is a whole set of examination methods, e.g. receiving all consecutive messages is a whole set of examination methods, e.g. receiving all consecutive messages
matching certain criteria, receiving a whole sequence of fixed messages or matching certain criteria, receiving a whole sequence of fixed messages or
classes, receiving nothing for some time, etc. classes, receiving nothing for some time, etc.
The ActorSystem passed in to the constructor of TestKit is accessible via the The ActorSystem passed to the constructor of TestKit is accessible via the
@scala[`system` member]@java[`getSystem()` method]. @scala[`system` member]@java[`getSystem()` method].
@@@ note @@@ note
@ -75,7 +75,7 @@ actor—are stopped.
### Built-In Assertions ### Built-In Assertions
The above mentioned @scala[`expectMsg`]@java[`expectMsgEquals`] is not the only method for formulating The above-mentioned @scala[`expectMsg`]@java[`expectMsgEquals`] is not the only method for formulating
assertions concerning received messages, the full set is this: assertions concerning received messages, the full set is this:
Scala Scala
@ -85,7 +85,7 @@ Java
: @@snip [TestKitDocTest.java](/akka-docs/src/test/java/jdocs/testkit/TestKitDocTest.java) { #test-expect } : @@snip [TestKitDocTest.java](/akka-docs/src/test/java/jdocs/testkit/TestKitDocTest.java) { #test-expect }
In these examples, the maximum durations you will find mentioned below are left In these examples, the maximum durations you will find mentioned below are left
out, in which case they use the default value from configuration item out, in which case they use the default value from the configuration item
`akka.test.single-expect-default` which itself defaults to 3 seconds (or they `akka.test.single-expect-default` which itself defaults to 3 seconds (or they
obey the innermost enclosing `Within` as detailed @ref:[below](#testkit-within)). The full signatures are: obey the innermost enclosing `Within` as detailed @ref:[below](#testkit-within)). The full signatures are:
@ -93,7 +93,7 @@ obey the innermost enclosing `Within` as detailed @ref:[below](#testkit-within))
The given message object must be received within the specified time; the The given message object must be received within the specified time; the
object will be returned. object will be returned.
* @scala[`expectMsgPF[T](d: Duration)(pf: PartialFunction[Any, T]): T`]@java[`public <T> T expectMsgPF(Duration max, String hint, Function<Object, T> f)`] * @scala[`expectMsgPF[T](d: Duration)(pf: PartialFunction[Any, T]): T`]@java[`public <T> T expectMsgPF(Duration max, String hint, Function<Object, T> f)`]
Within the given time period, a message must be received and the given Within the given time, a message must be received and the given
@scala[partial] function must be defined for that message; the result from applying @scala[partial] function must be defined for that message; the result from applying
the @scala[partial] function to the received message is returned. @scala[The duration may the @scala[partial] function to the received message is returned. @scala[The duration may
be left unspecified (empty parentheses are required in this case) to use be left unspecified (empty parentheses are required in this case) to use
@ -125,7 +125,7 @@ instance of at least one of the supplied `Class` objects; the
received object will be returned. Note that this does a conformance check, received object will be returned. Note that this does a conformance check,
if you need the class to be equal you need to verify that afterwards. if you need the class to be equal you need to verify that afterwards.
* @scala[`expectMsgAllOf[T](d: Duration, obj: T*): Seq[T]`]@java[`public List<Object> expectMsgAllOf(Duration max, Object... msg)`] * @scala[`expectMsgAllOf[T](d: Duration, obj: T*): Seq[T]`]@java[`public List<Object> expectMsgAllOf(Duration max, Object... msg)`]
A number of objects matching the size of the supplied object array must be Several objects matching the size of the supplied object array must be
received within the given time, and for each of the given objects there received within the given time, and for each of the given objects there
must exist at least one among the received ones which equals (compared with must exist at least one among the received ones which equals (compared with
@scala[`==`]@java[`equals()`]) it. The full sequence of received objects is returned in @scala[`==`]@java[`equals()`]) it. The full sequence of received objects is returned in
@ -134,13 +134,13 @@ the order received.
@@@ div { .group-scala } @@@ div { .group-scala }
* `expectMsgAllClassOf[T](d: Duration, c: Class[_ <: T]*): Seq[T]` * `expectMsgAllClassOf[T](d: Duration, c: Class[_ <: T]*): Seq[T]`
A number of objects matching the size of the supplied `Class` array Several objects matching the size of the supplied `Class` array
must be received within the given time, and for each of the given classes must be received within the given time, and for each of the given classes
there must exist at least one among the received objects whose class equals there must exist at least one among the received objects whose class equals
(compared with `==`) it (this is *not* a conformance check). The full (compared with `==`) it (this is *not* a conformance check). The full
sequence of received objects is returned. sequence of received objects is returned.
* `expectMsgAllConformingOf[T](d: Duration, c: Class[_ <: T]*): Seq[T]` * `expectMsgAllConformingOf[T](d: Duration, c: Class[_ <: T]*): Seq[T]`
A number of objects matching the size of the supplied `Class` array Several objects matching the size of the supplied `Class` array
must be received within the given time, and for each of the given classes must be received within the given time, and for each of the given classes
there must exist at least one among the received objects which is an there must exist at least one among the received objects which is an
instance of this class. The full sequence of received objects is returned. instance of this class. The full sequence of received objects is returned.
@ -185,7 +185,7 @@ Collect messages as long as
All collected messages are returned. @scala[The maximum duration defaults to the All collected messages are returned. @scala[The maximum duration defaults to the
time remaining in the innermost enclosing @ref:[within](#testkit-within) time remaining in the innermost enclosing @ref:[within](#testkit-within)
block and the idle duration defaults to infinity (thereby disabling the block and the idle duration defaults to infinity (thereby disabling the
idle timeout feature). The number of expected messages defaults to idle-timeout feature). The number of expected messages defaults to
`Int.MaxValue`, which effectively disables this limit.] `Int.MaxValue`, which effectively disables this limit.]
* @scala[`awaitCond(p: => Boolean, max: Duration, interval: Duration)`]@java[`public void awaitCond(Duration max, Duration interval, Supplier<Boolean> p)`] * @scala[`awaitCond(p: => Boolean, max: Duration, interval: Duration)`]@java[`public void awaitCond(Duration max, Duration interval, Supplier<Boolean> p)`]
@ -217,7 +217,7 @@ to ignore regular messages and are only interested in your specific ones.]
### Expecting Log Messages ### Expecting Log Messages
Since an integration test does not allow to the internal processing of the Since an integration test does not allow observing the internal processing of the
participating actors, verifying expected exceptions cannot be done directly. participating actors, verifying expected exceptions cannot be done directly.
Instead, use the logging system for this purpose: replacing the normal event Instead, use the logging system for this purpose: replacing the normal event
handler with the `TestEventListener` and using an `EventFilter` handler with the `TestEventListener` and using an `EventFilter`
@ -230,7 +230,7 @@ Scala
Java Java
: @@snip [TestKitDocTest.java](/akka-docs/src/test/java/jdocs/testkit/TestKitDocTest.java) { #test-event-filter } : @@snip [TestKitDocTest.java](/akka-docs/src/test/java/jdocs/testkit/TestKitDocTest.java) { #test-event-filter }
If a number of occurrences is specific—as demonstrated above—then `intercept` If the number of occurrences is specific—as demonstrated above—then `intercept`
will block until that number of matching messages have been received or the will block until that number of matching messages have been received or the
timeout configured in `akka.test.filter-leeway` is used up (time starts timeout configured in `akka.test.filter-leeway` is used up (time starts
counting after the passed-in block of code returns). In case of a timeout the counting after the passed-in block of code returns). In case of a timeout the
@ -251,7 +251,7 @@ akka.loggers = [akka.testkit.TestEventListener]
### Overriding behavior ### Overriding behavior
Sometimes you want to 'hook into' your actor to be able to test some internals. Sometimes you want to 'hook into' your actor to be able to test some internals.
Usually it is better to test an actors' external interface, but for example if Usually, it is better to test an actors' external interface, but for example if
you want to test timing-sensitive behavior this can come in handy. Say for you want to test timing-sensitive behavior this can come in handy. Say for
instance you want to test an actor that schedules a task: instance you want to test an actor that schedules a task:
@ -294,7 +294,7 @@ you do not specify it, it is inherited from the innermost enclosing
It should be noted that if the last message-receiving assertion of the block is It should be noted that if the last message-receiving assertion of the block is
`expectNoMessage` or `receiveWhile`, the final check of the `expectNoMessage` or `receiveWhile`, the final check of the
`within` is skipped in order to avoid false positives due to wake-up `within` is skipped to avoid false positives due to wake-up
latencies. This means that while individual contained assertions still use the latencies. This means that while individual contained assertions still use the
maximum time bound, the overall block may take arbitrarily longer in this case. maximum time bound, the overall block may take arbitrarily longer in this case.
@ -347,7 +347,7 @@ If you want the sender of messages inside your TestKit-based tests to be the `te
When the actors under test are supposed to send various messages to different When the actors under test are supposed to send various messages to different
destinations, it may be difficult distinguishing the message streams arriving destinations, it may be difficult distinguishing the message streams arriving
at the `testActor` when using the `TestKit` as @scala[a mixin]@java[shown until now]. Another at the `testActor` when using the `TestKit` as @scala[a mixin]@java[shown until now]. Another
approach is to use it for creation of simple probe actors to be inserted in the approach is to use it for the creation of simple probe actors to be inserted in the
message flows. @scala[To make this more powerful and convenient, there is a concrete message flows. @scala[To make this more powerful and convenient, there is a concrete
implementation called `TestProbe`.] The functionality is best explained implementation called `TestProbe`.] The functionality is best explained
using a small example: using a small example:
@ -364,8 +364,8 @@ Java
supposed to mirror its input to two outputs. Attaching two test probes enables supposed to mirror its input to two outputs. Attaching two test probes enables
verification of the (simplistic) behavior]@java[This simple test verifies an equally simple Forwarder actor by injecting a verification of the (simplistic) behavior]@java[This simple test verifies an equally simple Forwarder actor by injecting a
probe as the forwarders target]. Another example would be two actors probe as the forwarders target]. Another example would be two actors
A and B which collaborate by A sending messages to B. In order to verify this A and B which collaborate by A sending messages to B. To verify this
message flow, a `TestProbe` could be inserted as target of A, using the message flow, a `TestProbe` could be inserted as a target of A, using the
forwarding capabilities or auto-pilot described below to include a real B in forwarding capabilities or auto-pilot described below to include a real B in
the test setup. the test setup.
@ -388,16 +388,16 @@ Java
: @@snip [TestKitDocTest.java](/akka-docs/src/test/java/jdocs/testkit/TestKitDocTest.java) { #test-special-probe } : @@snip [TestKitDocTest.java](/akka-docs/src/test/java/jdocs/testkit/TestKitDocTest.java) { #test-special-probe }
You have complete flexibility here in mixing and matching the `TestKit` You have complete flexibility here in mixing and matching the `TestKit`
facilities with your own checks and choosing an intuitive name for it. In real facilities with your checks and choosing an intuitive name for it. In real
life your code will probably be a bit more complicated than the example given life your code will probably be a bit more complicated than the example given
above; just use the power! above; just use the power!
@@@ warning @@@ warning
Any message sent from a `TestProbe` to another actor which runs on the Any message sent from a `TestProbe` to another actor which runs on the
CallingThreadDispatcher runs the risk of dead-lock, if that other actor might CallingThreadDispatcher runs the risk of dead-lock if that other actor might
also send to this probe. The implementation of `TestProbe.watch` and also send to this probe. The implementation of `TestProbe.watch` and
`TestProbe.unwatch` will also send a message to the watchee, which `TestProbe.unwatch` will also send a message to the actor being watched, which
means that it is dangerous to try watching e.g. `TestActorRef` from a means that it is dangerous to try watching e.g. `TestActorRef` from a
`TestProbe`. `TestProbe`.
@ -448,7 +448,7 @@ had intervened.]
#### Auto-Pilot #### Auto-Pilot
Receiving messages in a queue for later inspection is nice, but in order to Receiving messages in a queue for later inspection is nice, but to
keep a test running and verify traces later you can also install an keep a test running and verify traces later you can also install an
`AutoPilot` in the participating test probes (actually in any `AutoPilot` in the participating test probes (actually in any
`TestKit`) which is invoked before enqueueing to the inspection queue. `TestKit`) which is invoked before enqueueing to the inspection queue.
@ -462,7 +462,7 @@ Java
: @@snip [TestKitDocTest.java](/akka-docs/src/test/java/jdocs/testkit/TestKitDocTest.java) { #test-auto-pilot } : @@snip [TestKitDocTest.java](/akka-docs/src/test/java/jdocs/testkit/TestKitDocTest.java) { #test-auto-pilot }
The `run` method must return the auto-pilot for the next message, @scala[which The `run` method must return the auto-pilot for the next message, @scala[which
may be `KeepRunning` to retain the current one or `NoAutoPilot` can be `KeepRunning` to retain the current one or `NoAutoPilot`
to switch it off]@java[wrapped to switch it off]@java[wrapped
in an `Option`; setting it to `None` terminates the auto-pilot]. in an `Option`; setting it to `None` terminates the auto-pilot].
@ -471,7 +471,7 @@ in an `Option`; setting it to `None` terminates the auto-pilot].
The behavior of `within` blocks when using test probes might be perceived The behavior of `within` blocks when using test probes might be perceived
as counter-intuitive: you need to remember that the nicely scoped deadline as as counter-intuitive: you need to remember that the nicely scoped deadline as
described @ref:[above](#testkit-within) is local to each probe. Hence, probes described @ref:[above](#testkit-within) is local to each probe. Hence, probes
do not react to each other's deadlines or to the deadline set in an enclosing do not react to each other's deadlines or the deadline set in an enclosing
`TestKit` instance: `TestKit` instance:
Scala Scala
@ -486,7 +486,7 @@ Here, the @scala[`expectMsg`]@java[`expectMsgEquals`] call will use the default
The parent of an actor is always the actor that created it. At times this leads to The parent of an actor is always the actor that created it. At times this leads to
a coupling between the two that may not be straightforward to test. a coupling between the two that may not be straightforward to test.
There are several approaches to improve testability of a child actor that There are several approaches to improve the testability of a child actor that
needs to refer to its parent: needs to refer to its parent:
1. when creating a child, pass an explicit reference to its parent 1. when creating a child, pass an explicit reference to its parent
@ -505,9 +505,9 @@ Scala
Java Java
: @@snip [ParentChildTest.java](/akka-docs/src/test/java/jdocs/testkit/ParentChildTest.java) { #test-example } : @@snip [ParentChildTest.java](/akka-docs/src/test/java/jdocs/testkit/ParentChildTest.java) { #test-example }
#### Introduce child to its parent #### Introduce a child to its parent
The first option is to avoid use of the `context.parent` function and create The first option is to avoid the use of the `context.parent` function and create
a child with a custom parent by passing an explicit reference to its parent instead. a child with a custom parent by passing an explicit reference to its parent instead.
Scala Scala
@ -518,7 +518,7 @@ Java
#### Create the child using @scala[TestProbe]@java[TestKit] #### Create the child using @scala[TestProbe]@java[TestKit]
The @scala[`TestProbe`]@java[`TestKit`] class can in fact create actors that will run with the test probe as parent. The @scala[`TestProbe`]@java[`TestKit`] class can create actors that will run with the test probe as a parent.
This will cause any messages the child actor sends to @scala[*context.parent*]@java[*getContext().getParent()*] to This will cause any messages the child actor sends to @scala[*context.parent*]@java[*getContext().getParent()*] to
end up in the test probe. end up in the test probe.
@ -580,7 +580,7 @@ The `CallingThreadDispatcher` runs invocations on the current thread only. This
dispatcher does not create any new threads. dispatcher does not create any new threads.
It is possible to use the `CallingThreadDispatcher` in unit testing, as It is possible to use the `CallingThreadDispatcher` in unit testing, as
described above, but originally it was conceived in order to allow contiguous described above, but originally it was conceived to allow uninterrupted
stack traces to be generated in case of an error. As this special dispatcher stack traces to be generated in case of an error. As this special dispatcher
runs everything which would normally be queued directly on the current thread, runs everything which would normally be queued directly on the current thread,
the full history of a message's processing chain is recorded on the call stack, the full history of a message's processing chain is recorded on the call stack,
@ -600,7 +600,7 @@ Java
When receiving an invocation, the `CallingThreadDispatcher` checks When receiving an invocation, the `CallingThreadDispatcher` checks
whether the receiving actor is already active on the current thread. The whether the receiving actor is already active on the current thread. The
simplest example for this situation is an actor which sends a message to simplest example of this situation is an actor which sends a message to
itself. In this case, processing cannot continue immediately as that would itself. In this case, processing cannot continue immediately as that would
violate the actor model, so the invocation is queued and will be processed when violate the actor model, so the invocation is queued and will be processed when
the active invocation on that actor finishes its processing; thus, it will be the active invocation on that actor finishes its processing; thus, it will be
@ -612,12 +612,12 @@ also executed immediately.
This scheme makes the `CallingThreadDispatcher` work like a general This scheme makes the `CallingThreadDispatcher` work like a general
purpose dispatcher for any actors which never block on external events. purpose dispatcher for any actors which never block on external events.
In the presence of multiple threads it may happen that two invocations of an In the presence of multiple threads, it may happen that two invocations of an
actor running on this dispatcher happen on two different threads at the same actor running on this dispatcher happen on two different threads at the same
time. In this case, both will be processed directly on their respective time. In this case, both will be processed directly on their respective
threads, where both compete for the actor's lock and the loser has to wait. threads, where both compete for the actor's lock and the loser has to wait.
Thus, the actor model is left intact, but the price is loss of concurrency due Thus, the actor model is left intact, but the price is the loss of concurrency due
to limited scheduling. In a sense this is equivalent to traditional mutex style to limited scheduling. In a sense, this is equivalent to traditional mutex style
concurrency. concurrency.
The other remaining difficulty is correct handling of suspend and resume: when The other remaining difficulty is correct handling of suspend and resume: when
@ -627,24 +627,23 @@ queues (the same ones used for queuing in the normal case). The call to
in the system will probably not be executing this specific actor, which leads in the system will probably not be executing this specific actor, which leads
to the problem that the thread-local queues cannot be emptied by their native to the problem that the thread-local queues cannot be emptied by their native
threads. Hence, the thread calling `resume` will collect all currently threads. Hence, the thread calling `resume` will collect all currently
queued invocations from all threads into its own queue and process them. queued invocations from all threads into its queue and process them.
### Limitations ### Limitations
@@@ warning @@@ warning
In case the CallingThreadDispatcher is used for top-level actors, but In case the CallingThreadDispatcher is used for top-level actors,
without going through TestActorRef, then there is a time window during which without going through TestActorRef, then there is a time window during which
the actor is awaiting construction by the user guardian actor. Sending the actor is awaiting construction by the user guardian actor. Sending
messages to the actor during this time period will result in them being messages to the actor during this time will result in them being
enqueued and then executed on the guardians thread instead of the callers enqueued and then executed on the guardians thread instead of the callers
thread. To avoid this, use TestActorRef. thread. To avoid this, use TestActorRef.
@@@ @@@
If an actor's behavior blocks on a something which would normally be affected If an actor's behavior blocks on something which would normally be affected
by the calling actor after having sent the message, this will obviously by the calling actor after having sent the message, this will dead-lock when using this dispatcher. This is a common scenario in actor tests
dead-lock when using this dispatcher. This is a common scenario in actor tests
based on `CountDownLatch` for synchronization: based on `CountDownLatch` for synchronization:
```scala ```scala
@ -661,8 +660,8 @@ normal dispatcher.
Thus, keep in mind that the `CallingThreadDispatcher` is not a Thus, keep in mind that the `CallingThreadDispatcher` is not a
general-purpose replacement for the normal dispatchers. If you are looking general-purpose replacement for the normal dispatchers. If you are looking
for a tool to help you debug dead-locks, for a tool to help you debug dead-locks,
the `CallingThreadDispatcher` may help with certain error the `CallingThreadDispatcher` may help with some error
scenarios, but keep in mind that it has may give false negatives as well as scenarios, but keep in mind that it may give false negatives as well as
false positives. false positives.
### Thread Interruptions ### Thread Interruptions
@ -681,7 +680,7 @@ threads interrupted flag will be set and processing continues normally.
@@@ note @@@ note
The summary of these two paragraphs is that if the current thread is In summary, if the current thread is
interrupted while doing work under the CallingThreadDispatcher, then that interrupted while doing work under the CallingThreadDispatcher, then that
will result in the `isInterrupted` flag to be `true` when the message will result in the `isInterrupted` flag to be `true` when the message
send returns and no `InterruptedException` will be thrown. send returns and no `InterruptedException` will be thrown.
@ -690,7 +689,7 @@ send returns and no `InterruptedException` will be thrown.
### Benefits ### Benefits
To summarize, these are the features with the `CallingThreadDispatcher` To summarize, these are the features that `CallingThreadDispatcher`
has to offer: has to offer:
* Deterministic execution of single-threaded tests while retaining nearly full * Deterministic execution of single-threaded tests while retaining nearly full
@ -709,7 +708,7 @@ by debuggers as well as logging, where the Akka toolkit offers the following
options: options:
* *Logging of exceptions thrown within Actor instances* * *Logging of exceptions thrown within Actor instances*
This is always on; in contrast to the other logging mechanisms, this logs at It is always on; in contrast to the other logging mechanisms, this logs at
`ERROR` level. `ERROR` level.
@@@ div { .group-scala } @@@ div { .group-scala }
@ -722,7 +721,7 @@ statement to be applied to an actors `receive` function:
If the aforementioned setting is not given in the @ref:[Configuration](general/configuration-reference.md#config-akka-actor), this method will If the aforementioned setting is not given in the @ref:[Configuration](general/configuration-reference.md#config-akka-actor), this method will
pass through the given `Receive` function unmodified, meaning that pass through the given `Receive` function unmodified, meaning that
there is no runtime cost unless actually enabled. there is no runtime cost unless enabled.
The logging feature is coupled to this specific local mark-up because The logging feature is coupled to this specific local mark-up because
enabling it uniformly on all actors is not usually what you need, and it enabling it uniformly on all actors is not usually what you need, and it
@ -740,7 +739,7 @@ actors.
enabling the setting `akka.actor.debug.lifecycle`; this, too, is enabled enabling the setting `akka.actor.debug.lifecycle`; this, too, is enabled
uniformly on all actors. uniformly on all actors.
All these messages are logged at `DEBUG` level. To summarize, you can enable Logging of these messages is at `DEBUG` level. To summarize, you can enable
full logging of actor activities using this configuration fragment: full logging of actor activities using this configuration fragment:
``` ```
@ -760,13 +759,13 @@ akka {
## Different Testing Frameworks ## Different Testing Frameworks
Akkas own test suite is written using [ScalaTest](http://www.scalatest.org), Akkas test suite is written using [ScalaTest](http://www.scalatest.org),
which also shines through in documentation examples. However, the TestKit and which also shines through in documentation examples. However, the TestKit and
its facilities do not depend on that framework, you can essentially use its facilities do not depend on that framework, so you can essentially use
whichever suits your development style best. whichever suits your development style best.
This section contains a collection of known gotchas with some other frameworks, This section contains a collection of known gotchas with some other frameworks,
which is by no means exhaustive and does not imply endorsement or special which is by no means exhaustive and does not imply an endorsement or special
support. support.
### When you need it to be a trait ### When you need it to be a trait
@ -788,21 +787,17 @@ backwards compatibility in the future, use at own risk.
Some [Specs2](https://etorreborre.github.io/specs2/) users have contributed examples of how to work around some clashes which may arise: Some [Specs2](https://etorreborre.github.io/specs2/) users have contributed examples of how to work around some clashes which may arise:
* Mixing TestKit into `org.specs2.mutable.Specification` results in a * Mixing TestKit into `org.specs2.mutable.Specification` results in a
name clash involving the `end` method (which is a private variable in name clash involving the `end` method (which is a private variable in
TestKit and an abstract method in Specification); if mixing in TestKit first, TestKit and an abstract method in Specification); if mixing in TestKit first,
the code may compile but might then fail at runtime. The work-around—which is the code may compile but might then fail at runtime. The workaround—which is
actually beneficial also for the third point—is to apply the TestKit together beneficial also for the third point—is to apply the TestKit together
with `org.specs2.specification.Scope`. with `org.specs2.specification.Scope`.
* The Specification traits provide a `Duration` DSL which uses partly * The Specification traits provide a `Duration` DSL which uses partly the same method names as `scala.concurrent.duration.Duration`, resulting in ambiguous implicits if `scala.concurrent.duration._` is imported. There are two workarounds:
the same method names as `scala.concurrent.duration.Duration`, resulting in ambiguous * either use the Specification variant of Duration and supply an implicit conversion to the Akka Duration. This conversion is not supplied with the
implicits if `scala.concurrent.duration._` is imported. There are two workarounds: Akka distribution because that would mean that our JAR files would depend on
* either use the Specification variant of Duration and supply an implicit Specs2, which is not justified by this little feature.
conversion to the Akka Duration. This conversion is not supplied with the * or mix `org.specs2.time.NoTimeConversions` into the Specification.
Akka distribution because that would mean that our JAR files would depend on * Specifications are by default executed concurrently, which requires some care when writing the tests or the `sequential` keyword.
Specs2, which is not justified by this little feature.
* or mix `org.specs2.time.NoTimeConversions` into the Specification.
* Specifications are by default executed concurrently, which requires some care
when writing the tests or alternatively the `sequential` keyword.
@@@ @@@
@ -835,12 +830,11 @@ integration tests.
Normally, the `ActorRef` shields the underlying `Actor` instance Normally, the `ActorRef` shields the underlying `Actor` instance
from the outside, the only communications channel is the actor's mailbox. This from the outside, the only communications channel is the actor's mailbox. This
restriction is an impediment to unit testing, which led to the inception of the restriction impedes unit testing, which led to the inception of the
`TestActorRef`. This special type of reference is designed specifically `TestActorRef`. This special type of reference is designed specifically
for test purposes and allows access to the actor in two ways: either by for test purposes and allows access to the actor in two ways: either by
obtaining a reference to the underlying actor instance, or by invoking or obtaining a reference to the underlying actor instance or by invoking or
querying the actor's behavior (`receive`). Each one warrants its own querying the actor's behavior (`receive`). Each one warrants its section below.
section below.
@@@ note @@@ note
@ -852,7 +846,7 @@ instead of using `TestActorRef` whenever possible.
@@@ warning @@@ warning
Due to the synchronous nature of `TestActorRef` it will **not** work with some support Due to the synchronous nature of `TestActorRef`, it will **not** work with some support
traits that Akka provides as they require asynchronous behaviors to function properly. traits that Akka provides as they require asynchronous behaviors to function properly.
Examples of traits that do not mix well with test actor refs are @ref:[PersistentActor](persistence.md#example) Examples of traits that do not mix well with test actor refs are @ref:[PersistentActor](persistence.md#example)
and @ref:[AtLeastOnceDelivery](persistence.md#at-least-once-delivery) provided by @ref:[Akka Persistence](persistence.md). and @ref:[AtLeastOnceDelivery](persistence.md#at-least-once-delivery) provided by @ref:[Akka Persistence](persistence.md).
@ -861,7 +855,7 @@ and @ref:[AtLeastOnceDelivery](persistence.md#at-least-once-delivery) provided b
### Obtaining a Reference to an `Actor` ### Obtaining a Reference to an `Actor`
Having access to the actual `Actor` object allows application of all Having access to the actual `Actor` object allows the application of all
traditional unit testing techniques on the contained methods. Obtaining a traditional unit testing techniques on the contained methods. Obtaining a
reference is done like this: reference is done like this:
@ -881,9 +875,9 @@ any unit testing tool to bear on your actor as usual.
<a id="testfsmref"></a> <a id="testfsmref"></a>
### Testing Finite State Machines ### Testing Finite State Machines
If your actor under test is a `FSM`, you may use the special If your actor under test is an `FSM`, you may use the special
`TestFSMRef` which offers all features of a normal `TestActorRef` `TestFSMRef` which offers all features of a normal `TestActorRef`
and in addition allows access to the internal state: and besides allows access to the internal state:
@@snip [TestkitDocSpec.scala](/akka-docs/src/test/scala/docs/testkit/TestkitDocSpec.scala) { #test-fsm-ref } @@snip [TestkitDocSpec.scala](/akka-docs/src/test/scala/docs/testkit/TestkitDocSpec.scala) { #test-fsm-ref }
@ -893,7 +887,7 @@ instead of the hypothetical `ActorRef`-inspired `TestFSMRef[MyFSM]`.
All methods shown above directly access the FSM state without any All methods shown above directly access the FSM state without any
synchronization; this is perfectly alright if the `CallingThreadDispatcher` synchronization; this is perfectly alright if the `CallingThreadDispatcher`
is used and no other threads are involved, but it may lead to surprises if you is used and no other threads are involved, but it may lead to surprises if you
were to actually exercise timer events, because those are executed on the were to exercise timer events, because those are executed on the
`Scheduler` thread. `Scheduler` thread.
@@@ @@@
@ -901,8 +895,8 @@ were to actually exercise timer events, because those are executed on the
### Testing the Actor's Behavior ### Testing the Actor's Behavior
When the dispatcher invokes the processing behavior of an actor on a message, When the dispatcher invokes the processing behavior of an actor on a message,
it actually calls `apply` on the current behavior registered for the it calls `apply` on the current behavior registered for the
actor. This starts out with the return value of the declared `receive` actor. This starts with the return value of the declared `receive`
method, but it may also be changed using `become` and `unbecome` in method, but it may also be changed using `become` and `unbecome` in
response to external messages. All of this contributes to the overall actor response to external messages. All of this contributes to the overall actor
behavior and it does not lend itself to easy testing on the `Actor` behavior and it does not lend itself to easy testing on the `Actor`
@ -942,7 +936,7 @@ dispatcher to `CallingThreadDispatcher.global` and it sets the
### The Way In-Between: Expecting Exceptions ### The Way In-Between: Expecting Exceptions
If you want to test the actor behavior, including hotswapping, but without If you want to test the actor behavior, including hot swapping, but without
involving a dispatcher and without having the `TestActorRef` swallow involving a dispatcher and without having the `TestActorRef` swallow
any thrown exceptions, then there is another mode available for you: use any thrown exceptions, then there is another mode available for you: use
the `receive` method on `TestActorRef`, which will be forwarded to the the `receive` method on `TestActorRef`, which will be forwarded to the