对象 testkit 不是包 akka 的成员
object testkit is not a member of package akka
我正在尝试 运行 Akka FSM 的示例代码,但我遇到了一些错误
[info] Loading project definition from /home/akka/fsm/project
[info] Loading settings for project root from build.sbt ...
[info] Set current project to fsm (in build file:/home/akka/fsm/)
[info] Executing in batch mode. For better performance use sbt's shell
[info] Compiling 1 Scala source to /home/akka/fsm/target/scala-2.13/classes ...
[error] /home/akka/fsm/src/main/scala/FSMDocSpec.scala:9:13: object testkit is not a member of package akka
[error] import akka.testkit.{ AkkaSpec => MyFavoriteTestFrameWorkPlusAkkaTestKit }
[error] ^
[error] /home/akka/fsm/src/main/scala/FSMDocSpec.scala:11:13: object testkit is not a member of package akka
[error] import akka.testkit._
[error] ^
[error] /home/akka/fsm/src/main/scala/FSMDocSpec.scala:43:26: not found: type MyFavoriteTestFrameWorkPlusAkkaTestKit
[error] class FSMDocSpec extends MyFavoriteTestFrameWorkPlusAkkaTestKit {
[error] ^
[error] /home/akka/fsm/src/main/scala/FSMDocSpec.scala:203:33: value must is not a member of String
[error] "simple finite state machine" must {
[error] ^
[error] /home/akka/fsm/src/main/scala/FSMDocSpec.scala:205:32: value in is not a member of String
[error] "demonstrate NullFunction" in {
[error] ^
[error] /home/akka/fsm/src/main/scala/FSMDocSpec.scala:214:23: value in is not a member of String
[error] "batch correctly" in {
[error] ^
[error] /home/akka/fsm/src/main/scala/FSMDocSpec.scala:215:21: not found: value system
[error] val buncher = system.actorOf(Props(classOf[Buncher], this))
[error] ^
[error] /home/akka/fsm/src/main/scala/FSMDocSpec.scala:219:7: not found: value expectMsg
[error] expectMsg(Batch(immutable.Seq(42, 43)))
[error] ^
[error] /home/akka/fsm/src/main/scala/FSMDocSpec.scala:223:7: not found: value expectMsg
[error] expectMsg(Batch(immutable.Seq(44)))
[error] ^
[error] /home/akka/fsm/src/main/scala/FSMDocSpec.scala:224:7: not found: value expectMsg
[error] expectMsg(Batch(immutable.Seq(45)))
[error] ^
[error] /home/akka/fsm/src/main/scala/FSMDocSpec.scala:227:34: value in is not a member of String
[error] "not batch if uninitialized" in {
[error] ^
[error] /home/akka/fsm/src/main/scala/FSMDocSpec.scala:228:21: not found: value system
[error] val buncher = system.actorOf(Props(classOf[Buncher], this))
[error] ^
[error] /home/akka/fsm/src/main/scala/FSMDocSpec.scala:230:7: not found: value expectNoMsg
[error] expectNoMsg
[error] ^
[error] 13 errors found
我的代码是这样的:
import language.postfixOps
import akka.testkit.{ AkkaSpec => MyFavoriteTestFrameWorkPlusAkkaTestKit }
import akka.util.ByteString
import akka.testkit._
//#test-code
import akka.actor.Props
import scala.collection.immutable
object FSMDocSpec {
// messages and data types
//#test-code
import akka.actor.ActorRef
//#simple-events
// received events
final case class SetTarget(ref: ActorRef)
final case class Queue(obj: Any)
case object Flush
// sent events
final case class Batch(obj: immutable.Seq[Any])
//#simple-events
//#simple-state
// states
sealed trait State
case object Idle extends State
case object Active extends State
sealed trait Data
case object Uninitialized extends Data
final case class Todo(target: ActorRef, queue: immutable.Seq[Any]) extends Data
//#simple-state
//#test-code
}
class FSMDocSpec extends MyFavoriteTestFrameWorkPlusAkkaTestKit {
import FSMDocSpec._
//#fsm-code-elided
//#simple-imports
import akka.actor.{ ActorRef, FSM }
import scala.concurrent.duration._
//#simple-imports
//#simple-fsm
class Buncher extends FSM[State, Data] {
//#fsm-body
startWith(Idle, Uninitialized)
//#when-syntax
when(Idle) {
case Event(SetTarget(ref), Uninitialized) =>
stay.using(Todo(ref, Vector.empty))
}
//#when-syntax
//#transition-elided
onTransition {
case Active -> Idle =>
stateData match {
case Todo(ref, queue) => ref ! Batch(queue)
case _ => // nothing to do
}
}
//#transition-elided
//#when-syntax
when(Active, stateTimeout = 1 second) {
case Event(Flush | StateTimeout, t: Todo) =>
goto(Idle).using(t.copy(queue = Vector.empty))
}
//#when-syntax
//#unhandled-elided
whenUnhandled {
// common code for both states
case Event(Queue(obj), t @ Todo(_, v)) =>
goto(Active).using(t.copy(queue = v :+ obj))
case Event(e, s) =>
log.warning("received unhandled request {} in state {}/{}", e, stateName, s)
stay
}
//#unhandled-elided
//#fsm-body
initialize()
}
//#simple-fsm
object DemoCode {
trait StateType
case object SomeState extends StateType
case object Processing extends StateType
case object Error extends StateType
case object Idle extends StateType
case object Active extends StateType
class Dummy extends FSM[StateType, Int] {
class X
val newData = 42
object WillDo
object Tick
//#modifier-syntax
when(SomeState) {
case Event(msg, _) =>
goto(Processing).using(newData).forMax(5 seconds).replying(WillDo)
}
//#modifier-syntax
//#transition-syntax
onTransition {
case Idle -> Active => startTimerWithFixedDelay("timeout", Tick, 1 second)
case Active -> _ => cancelTimer("timeout")
case x -> Idle => log.info("entering Idle from " + x)
}
//#transition-syntax
//#alt-transition-syntax
onTransition(handler _)
def handler(from: StateType, to: StateType): Unit = {
// handle it here ...
}
//#alt-transition-syntax
//#stop-syntax
when(Error) {
case Event("stop", _) =>
// do cleanup ...
stop()
}
//#stop-syntax
//#transform-syntax
when(SomeState)(transform {
case Event(bytes: ByteString, read) => stay.using(read + bytes.length)
}.using {
case s @ FSM.State(state, read, timeout, stopReason, replies) if read > 1000 =>
goto(Processing)
})
//#transform-syntax
//#alt-transform-syntax
val processingTrigger: PartialFunction[State, State] = {
case s @ FSM.State(state, read, timeout, stopReason, replies) if read > 1000 =>
goto(Processing)
}
when(SomeState)(transform {
case Event(bytes: ByteString, read) => stay.using(read + bytes.length)
}.using(processingTrigger))
//#alt-transform-syntax
//#termination-syntax
onTermination {
case StopEvent(FSM.Normal, state, data) => // ...
case StopEvent(FSM.Shutdown, state, data) => // ...
case StopEvent(FSM.Failure(cause), state, data) => // ...
}
//#termination-syntax
//#unhandled-syntax
whenUnhandled {
case Event(x: X, data) =>
log.info("Received unhandled event: " + x)
stay
case Event(msg, _) =>
log.warning("Received unknown event: " + msg)
goto(Error)
}
//#unhandled-syntax
}
//#logging-fsm
import akka.actor.LoggingFSM
class MyFSM extends LoggingFSM[StateType, Data] {
//#body-elided
override def logDepth = 12
onTermination {
case StopEvent(FSM.Failure(_), state, data) =>
val lastEvents = getLog.mkString("\n\t")
log.warning(
"Failure in state " + state + " with data " + data + "\n" +
"Events leading up to this point:\n\t" + lastEvents)
}
// ...
//#body-elided
}
//#logging-fsm
}
//#fsm-code-elided
"simple finite state machine" must {
"demonstrate NullFunction" in {
class A extends FSM[Int, Null] {
val SomeState = 0
//#NullFunction
when(SomeState)(FSM.NullFunction)
//#NullFunction
}
}
"batch correctly" in {
val buncher = system.actorOf(Props(classOf[Buncher], this))
buncher ! SetTarget(testActor)
buncher ! Queue(42)
buncher ! Queue(43)
expectMsg(Batch(immutable.Seq(42, 43)))
buncher ! Queue(44)
buncher ! Flush
buncher ! Queue(45)
expectMsg(Batch(immutable.Seq(44)))
expectMsg(Batch(immutable.Seq(45)))
}
"not batch if uninitialized" in {
val buncher = system.actorOf(Props(classOf[Buncher], this))
buncher ! Queue(42)
expectNoMsg
}
}
}
//#test-code
build.sbt 就像:
lazy val root = (project in file(".")).settings (
name := "fsm",
version := "1.0",
scalaVersion := "2.13.1",
scalacOptions in ThisBuild ++= Seq("-unchecked", "-deprecation"),
resolvers += "Typesafe Repository" at "https://repo.typesafe.com/typesafe/releases/",
//libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.1" % Test,
//libraryDependencies += "org.scalactic" %% "scalactic" % "3.0.0",
libraryDependencies += "org.scalatest" %% "scalatest" % "3.1.2" % "test",
libraryDependencies += "com.typesafe.akka" %% "akka-testkit" % "2.6.5" % Test,
libraryDependencies += "com.typesafe.akka" %% "akka-actor" % "2.6.5"
)
我正在遵循以下指南:
https://doc.akka.io/docs/akka/current/fsm.html
但我无法获得此代码 运行.
我怀疑我在 build.sbt 文件中做错了,但经过一整天的搜索和尝试,我一无所获。同样的错误迫在眉睫,我想知道这里出了什么问题。
您应该将 FSMDocSpec.scala
移动到 src/test/scala
目录,而不是 src/main/scala
。这将在编译该文件时将测试范围的依赖项放在类路径上。
在您的 build.sbt
中,scalatest
和 akka-testkit
依赖项被指定为测试配置的范围:
libraryDependencies += "org.scalatest" %% "scalatest" % "3.1.2" % "test",
libraryDependencies += "com.typesafe.akka" %% "akka-testkit" % "2.6.5" % Test,
这 是 指定仅在 运行 测试时使用的依赖项的正确方法,而不是在主应用程序运行时使用,因此这不是错误你的 sbt 配置。这些依赖项仅在测试配置中 运行 时可用,在编译和 运行 测试时使用。在编译和 运行 主应用程序时,它们不会在类路径中,这允许您从生产应用程序中排除不必要的库。字符串 "test"
和常量 Test
是等价的,所以你可以选择其中一个并使用它来使两个依赖项保持一致,但这样做并不重要。
测试源代码本身必须在src/test/scala
里面。 src/main/scala
目录应该只用于主要应用程序代码,并且将在没有类路径上的测试依赖项的情况下编译。
sbt 文档中有更多详细信息,例如 "Scoping by the configuration axis"。
我正在尝试 运行 Akka FSM 的示例代码,但我遇到了一些错误
[info] Loading project definition from /home/akka/fsm/project
[info] Loading settings for project root from build.sbt ...
[info] Set current project to fsm (in build file:/home/akka/fsm/)
[info] Executing in batch mode. For better performance use sbt's shell
[info] Compiling 1 Scala source to /home/akka/fsm/target/scala-2.13/classes ...
[error] /home/akka/fsm/src/main/scala/FSMDocSpec.scala:9:13: object testkit is not a member of package akka
[error] import akka.testkit.{ AkkaSpec => MyFavoriteTestFrameWorkPlusAkkaTestKit }
[error] ^
[error] /home/akka/fsm/src/main/scala/FSMDocSpec.scala:11:13: object testkit is not a member of package akka
[error] import akka.testkit._
[error] ^
[error] /home/akka/fsm/src/main/scala/FSMDocSpec.scala:43:26: not found: type MyFavoriteTestFrameWorkPlusAkkaTestKit
[error] class FSMDocSpec extends MyFavoriteTestFrameWorkPlusAkkaTestKit {
[error] ^
[error] /home/akka/fsm/src/main/scala/FSMDocSpec.scala:203:33: value must is not a member of String
[error] "simple finite state machine" must {
[error] ^
[error] /home/akka/fsm/src/main/scala/FSMDocSpec.scala:205:32: value in is not a member of String
[error] "demonstrate NullFunction" in {
[error] ^
[error] /home/akka/fsm/src/main/scala/FSMDocSpec.scala:214:23: value in is not a member of String
[error] "batch correctly" in {
[error] ^
[error] /home/akka/fsm/src/main/scala/FSMDocSpec.scala:215:21: not found: value system
[error] val buncher = system.actorOf(Props(classOf[Buncher], this))
[error] ^
[error] /home/akka/fsm/src/main/scala/FSMDocSpec.scala:219:7: not found: value expectMsg
[error] expectMsg(Batch(immutable.Seq(42, 43)))
[error] ^
[error] /home/akka/fsm/src/main/scala/FSMDocSpec.scala:223:7: not found: value expectMsg
[error] expectMsg(Batch(immutable.Seq(44)))
[error] ^
[error] /home/akka/fsm/src/main/scala/FSMDocSpec.scala:224:7: not found: value expectMsg
[error] expectMsg(Batch(immutable.Seq(45)))
[error] ^
[error] /home/akka/fsm/src/main/scala/FSMDocSpec.scala:227:34: value in is not a member of String
[error] "not batch if uninitialized" in {
[error] ^
[error] /home/akka/fsm/src/main/scala/FSMDocSpec.scala:228:21: not found: value system
[error] val buncher = system.actorOf(Props(classOf[Buncher], this))
[error] ^
[error] /home/akka/fsm/src/main/scala/FSMDocSpec.scala:230:7: not found: value expectNoMsg
[error] expectNoMsg
[error] ^
[error] 13 errors found
我的代码是这样的:
import language.postfixOps
import akka.testkit.{ AkkaSpec => MyFavoriteTestFrameWorkPlusAkkaTestKit }
import akka.util.ByteString
import akka.testkit._
//#test-code
import akka.actor.Props
import scala.collection.immutable
object FSMDocSpec {
// messages and data types
//#test-code
import akka.actor.ActorRef
//#simple-events
// received events
final case class SetTarget(ref: ActorRef)
final case class Queue(obj: Any)
case object Flush
// sent events
final case class Batch(obj: immutable.Seq[Any])
//#simple-events
//#simple-state
// states
sealed trait State
case object Idle extends State
case object Active extends State
sealed trait Data
case object Uninitialized extends Data
final case class Todo(target: ActorRef, queue: immutable.Seq[Any]) extends Data
//#simple-state
//#test-code
}
class FSMDocSpec extends MyFavoriteTestFrameWorkPlusAkkaTestKit {
import FSMDocSpec._
//#fsm-code-elided
//#simple-imports
import akka.actor.{ ActorRef, FSM }
import scala.concurrent.duration._
//#simple-imports
//#simple-fsm
class Buncher extends FSM[State, Data] {
//#fsm-body
startWith(Idle, Uninitialized)
//#when-syntax
when(Idle) {
case Event(SetTarget(ref), Uninitialized) =>
stay.using(Todo(ref, Vector.empty))
}
//#when-syntax
//#transition-elided
onTransition {
case Active -> Idle =>
stateData match {
case Todo(ref, queue) => ref ! Batch(queue)
case _ => // nothing to do
}
}
//#transition-elided
//#when-syntax
when(Active, stateTimeout = 1 second) {
case Event(Flush | StateTimeout, t: Todo) =>
goto(Idle).using(t.copy(queue = Vector.empty))
}
//#when-syntax
//#unhandled-elided
whenUnhandled {
// common code for both states
case Event(Queue(obj), t @ Todo(_, v)) =>
goto(Active).using(t.copy(queue = v :+ obj))
case Event(e, s) =>
log.warning("received unhandled request {} in state {}/{}", e, stateName, s)
stay
}
//#unhandled-elided
//#fsm-body
initialize()
}
//#simple-fsm
object DemoCode {
trait StateType
case object SomeState extends StateType
case object Processing extends StateType
case object Error extends StateType
case object Idle extends StateType
case object Active extends StateType
class Dummy extends FSM[StateType, Int] {
class X
val newData = 42
object WillDo
object Tick
//#modifier-syntax
when(SomeState) {
case Event(msg, _) =>
goto(Processing).using(newData).forMax(5 seconds).replying(WillDo)
}
//#modifier-syntax
//#transition-syntax
onTransition {
case Idle -> Active => startTimerWithFixedDelay("timeout", Tick, 1 second)
case Active -> _ => cancelTimer("timeout")
case x -> Idle => log.info("entering Idle from " + x)
}
//#transition-syntax
//#alt-transition-syntax
onTransition(handler _)
def handler(from: StateType, to: StateType): Unit = {
// handle it here ...
}
//#alt-transition-syntax
//#stop-syntax
when(Error) {
case Event("stop", _) =>
// do cleanup ...
stop()
}
//#stop-syntax
//#transform-syntax
when(SomeState)(transform {
case Event(bytes: ByteString, read) => stay.using(read + bytes.length)
}.using {
case s @ FSM.State(state, read, timeout, stopReason, replies) if read > 1000 =>
goto(Processing)
})
//#transform-syntax
//#alt-transform-syntax
val processingTrigger: PartialFunction[State, State] = {
case s @ FSM.State(state, read, timeout, stopReason, replies) if read > 1000 =>
goto(Processing)
}
when(SomeState)(transform {
case Event(bytes: ByteString, read) => stay.using(read + bytes.length)
}.using(processingTrigger))
//#alt-transform-syntax
//#termination-syntax
onTermination {
case StopEvent(FSM.Normal, state, data) => // ...
case StopEvent(FSM.Shutdown, state, data) => // ...
case StopEvent(FSM.Failure(cause), state, data) => // ...
}
//#termination-syntax
//#unhandled-syntax
whenUnhandled {
case Event(x: X, data) =>
log.info("Received unhandled event: " + x)
stay
case Event(msg, _) =>
log.warning("Received unknown event: " + msg)
goto(Error)
}
//#unhandled-syntax
}
//#logging-fsm
import akka.actor.LoggingFSM
class MyFSM extends LoggingFSM[StateType, Data] {
//#body-elided
override def logDepth = 12
onTermination {
case StopEvent(FSM.Failure(_), state, data) =>
val lastEvents = getLog.mkString("\n\t")
log.warning(
"Failure in state " + state + " with data " + data + "\n" +
"Events leading up to this point:\n\t" + lastEvents)
}
// ...
//#body-elided
}
//#logging-fsm
}
//#fsm-code-elided
"simple finite state machine" must {
"demonstrate NullFunction" in {
class A extends FSM[Int, Null] {
val SomeState = 0
//#NullFunction
when(SomeState)(FSM.NullFunction)
//#NullFunction
}
}
"batch correctly" in {
val buncher = system.actorOf(Props(classOf[Buncher], this))
buncher ! SetTarget(testActor)
buncher ! Queue(42)
buncher ! Queue(43)
expectMsg(Batch(immutable.Seq(42, 43)))
buncher ! Queue(44)
buncher ! Flush
buncher ! Queue(45)
expectMsg(Batch(immutable.Seq(44)))
expectMsg(Batch(immutable.Seq(45)))
}
"not batch if uninitialized" in {
val buncher = system.actorOf(Props(classOf[Buncher], this))
buncher ! Queue(42)
expectNoMsg
}
}
}
//#test-code
build.sbt 就像:
lazy val root = (project in file(".")).settings (
name := "fsm",
version := "1.0",
scalaVersion := "2.13.1",
scalacOptions in ThisBuild ++= Seq("-unchecked", "-deprecation"),
resolvers += "Typesafe Repository" at "https://repo.typesafe.com/typesafe/releases/",
//libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.1" % Test,
//libraryDependencies += "org.scalactic" %% "scalactic" % "3.0.0",
libraryDependencies += "org.scalatest" %% "scalatest" % "3.1.2" % "test",
libraryDependencies += "com.typesafe.akka" %% "akka-testkit" % "2.6.5" % Test,
libraryDependencies += "com.typesafe.akka" %% "akka-actor" % "2.6.5"
)
我正在遵循以下指南: https://doc.akka.io/docs/akka/current/fsm.html 但我无法获得此代码 运行.
我怀疑我在 build.sbt 文件中做错了,但经过一整天的搜索和尝试,我一无所获。同样的错误迫在眉睫,我想知道这里出了什么问题。
您应该将 FSMDocSpec.scala
移动到 src/test/scala
目录,而不是 src/main/scala
。这将在编译该文件时将测试范围的依赖项放在类路径上。
在您的 build.sbt
中,scalatest
和 akka-testkit
依赖项被指定为测试配置的范围:
libraryDependencies += "org.scalatest" %% "scalatest" % "3.1.2" % "test",
libraryDependencies += "com.typesafe.akka" %% "akka-testkit" % "2.6.5" % Test,
这 是 指定仅在 运行 测试时使用的依赖项的正确方法,而不是在主应用程序运行时使用,因此这不是错误你的 sbt 配置。这些依赖项仅在测试配置中 运行 时可用,在编译和 运行 测试时使用。在编译和 运行 主应用程序时,它们不会在类路径中,这允许您从生产应用程序中排除不必要的库。字符串 "test"
和常量 Test
是等价的,所以你可以选择其中一个并使用它来使两个依赖项保持一致,但这样做并不重要。
测试源代码本身必须在src/test/scala
里面。 src/main/scala
目录应该只用于主要应用程序代码,并且将在没有类路径上的测试依赖项的情况下编译。
sbt 文档中有更多详细信息,例如 "Scoping by the configuration axis"。