diff --git a/akka-docs/rst/java/code/docs/testkit/TestKitDocTest.java b/akka-docs/rst/java/code/docs/testkit/TestKitDocTest.java index 1d85fdc8f6..44d66f095b 100644 --- a/akka-docs/rst/java/code/docs/testkit/TestKitDocTest.java +++ b/akka-docs/rst/java/code/docs/testkit/TestKitDocTest.java @@ -285,6 +285,19 @@ public class TestKitDocTest { //#test-probe } + @Test + public void demonstrateTestProbeWithCustomName() { + //#test-probe-with-custom-name + new JavaTestKit(system) {{ + final TestProbe worker = new TestProbe(system, "worker"); + final TestProbe aggregator = new TestProbe(system, "aggregator"); + + assertTrue(worker.ref().path().name().startsWith("worker")); + assertTrue(aggregator.ref().path().name().startsWith("aggregator")); + }}; + //#test-probe-with-custom-name + } + @Test public void demonstrateSpecialProbe() { //#test-special-probe diff --git a/akka-docs/rst/java/testing.rst b/akka-docs/rst/java/testing.rst index b54e88ff89..f3ce9f5d16 100644 --- a/akka-docs/rst/java/testing.rst +++ b/akka-docs/rst/java/testing.rst @@ -388,6 +388,11 @@ flow, a :class:`TestProbe` could be inserted as target of A, using the forwarding capabilities or auto-pilot described below to include a real B in the test setup. +If you have many test probes, you can name them to get meaningful actor names +in test logs and assertions: + +.. includecode:: code/docs/testkit/TestKitDocTest.java#test-probe-with-custom-name + Probes may also be equipped with custom assertions to make your test code even more concise and clear: diff --git a/akka-docs/rst/scala/code/docs/testkit/TestkitDocSpec.scala b/akka-docs/rst/scala/code/docs/testkit/TestkitDocSpec.scala index a56f129b22..bb27caf3db 100644 --- a/akka-docs/rst/scala/code/docs/testkit/TestkitDocSpec.scala +++ b/akka-docs/rst/scala/code/docs/testkit/TestkitDocSpec.scala @@ -211,6 +211,16 @@ class TestkitDocSpec extends AkkaSpec with DefaultTimeout with ImplicitSender { //#test-special-probe } + "demonstrate usage of test probe with custom name" in { + //#test-probe-with-custom-name + val worker = TestProbe("worker") + val aggregator = TestProbe("aggregator") + + worker.ref.path.name should startWith("worker") + aggregator.ref.path.name should startWith("aggregator") + //#test-probe-with-custom-name + } + "demonstrate probe watch" in { import akka.testkit.TestProbe val target = system.actorOf(Props.empty) diff --git a/akka-docs/rst/scala/testing.rst b/akka-docs/rst/scala/testing.rst index 5cbaaa8010..51a0e09a23 100644 --- a/akka-docs/rst/scala/testing.rst +++ b/akka-docs/rst/scala/testing.rst @@ -443,6 +443,11 @@ message flow, a :class:`TestProbe` could be inserted as target of A, using the forwarding capabilities or auto-pilot described below to include a real B in the test setup. +If you have many test probes, you can name them to get meaningful actor names +in test logs and assertions: + +.. includecode:: code/docs/testkit/TestkitDocSpec.scala#test-probe-with-custom-name + Probes may also be equipped with custom assertions to make your test code even more concise and clear: diff --git a/akka-testkit/src/main/scala/akka/testkit/TestKit.scala b/akka-testkit/src/main/scala/akka/testkit/TestKit.scala index 3663145474..b38ec43276 100644 --- a/akka-testkit/src/main/scala/akka/testkit/TestKit.scala +++ b/akka-testkit/src/main/scala/akka/testkit/TestKit.scala @@ -116,6 +116,11 @@ trait TestKitBase { def lastSender = lastMessage.sender + /** + * Defines the testActor name. + */ + protected def testActorName: String = "testActor" + /** * ActorRef of the test actor. Access is provided to enable e.g. * registration as message target. @@ -124,7 +129,7 @@ trait TestKitBase { val impl = system.asInstanceOf[ExtendedActorSystem] val ref = impl.systemActorOf(TestActor.props(queue) .withDispatcher(CallingThreadDispatcher.Id), - "testActor" + TestKit.testActorId.incrementAndGet) + "%s-%d".format(testActorName, TestKit.testActorId.incrementAndGet)) awaitCond(ref match { case r: RepointableRef ⇒ r.isStarted case _ ⇒ true @@ -787,13 +792,17 @@ object TestKit { /** * TestKit-based probe which allows sending, reception and reply. */ -class TestProbe(_application: ActorSystem) extends TestKit(_application) { +class TestProbe(_application: ActorSystem, name: String) extends TestKit(_application) { + + def this(_application: ActorSystem) = this(_application, "testProbe") /** * Shorthand to get the testActor. */ def ref = testActor + protected override def testActorName = name + /** * Send message to an actor while using the probe's TestActor as the sender. * Replies will be available for inspection with all of TestKit's assertion @@ -820,6 +829,7 @@ class TestProbe(_application: ActorSystem) extends TestKit(_application) { object TestProbe { def apply()(implicit system: ActorSystem) = new TestProbe(system) + def apply(name: String)(implicit system: ActorSystem) = new TestProbe(system, name) } trait ImplicitSender { this: TestKitBase ⇒ diff --git a/akka-testkit/src/test/scala/akka/testkit/TestProbeSpec.scala b/akka-testkit/src/test/scala/akka/testkit/TestProbeSpec.scala index 5db387be49..cd98734b10 100644 --- a/akka-testkit/src/test/scala/akka/testkit/TestProbeSpec.scala +++ b/akka-testkit/src/test/scala/akka/testkit/TestProbeSpec.scala @@ -2,11 +2,8 @@ package akka.testkit import language.postfixOps -import org.scalatest.WordSpec -import org.scalatest.Matchers -import org.scalatest.{ BeforeAndAfterEach, WordSpec } import akka.actor._ -import scala.concurrent.{ Future, Await } +import scala.concurrent.{ Await } import scala.concurrent.duration._ import akka.pattern.ask import scala.util.Try @@ -132,6 +129,15 @@ class TestProbeSpec extends AkkaSpec with DefaultTimeout { probe.expectMsg(1.seconds, Terminated(target)(false, false)) } + "allow user-defined name" in { + val probe = TestProbe("worker") + probe.ref.path.name should startWith("worker") + } + + "have reasonable default name" in { + val probe = new TestProbe(system) + probe.ref.path.name should startWith("testProbe") + } } }