对象测试包不是akka软件包的成员

时间:2020-06-02 02:52:31

标签: scala akka akka-fsm

我正在尝试运行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文件中做错了,但是经过一整天的搜索和尝试,我一无所获。即将出现同样的错误,我想知道这里出了什么问题。

1 个答案:

答案 0 :(得分:1)

您应该将FSMDocSpec.scala移至src/test/scala目录,而不是src/main/scala。编译该文件时,这会将测试作用域的依赖项放在类路径上。

在您的build.sbt中,将scalatestakka-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"

相关问题