Scala编译器错误:包api没有成员materializeWeakTypeTag

时间:2014-02-06 18:18:35

标签: scala intellij-idea akka scalatest

我是scala的新手,所以我很乐意接受我做错了什么!

我正在玩Akka,并使用scalatest和akka-testkit进行测试。这是我的build.sbt config

name := """EventHub"""

version := "1.0"

scalaVersion := "2.10.3"

libraryDependencies ++= Seq(
  "com.typesafe.akka" % "akka-actor_2.10" % "2.2.3",
  "com.typesafe.akka" % "akka-testKit_2.10" % "2.2.3" % "test",
  "org.scalatest" % "scalatest_2.10.0-M4" % "1.9-2.10.0-M4-B2" % "test",
  "com.ning" % "async-http-client" % "1.8.1"
)

当我编译时,我收到一条我不理解的消息。我有谷歌这个,并找到相关的scala编译器问题和错误。我不知道这是我所看到的,还是我在某处犯了一个基本错误。以下是输出的摘要(为简洁起见,我删除了很多“噪音”;如果需要可以添加更多细节!):

scalac: 
     while compiling: /Users/robert/Documents/Programming/Scala/Projects/EventHub/src/test/scala/Hub/Subscription/SubscriberSpec.scala
        during phase: typer
     library version: version 2.10.3
    compiler version: version 2.10.3
...
...
== Expanded type of tree ==
TypeRef(
  TypeSymbol(
    class SubscriberSpec extends TestKit with WordSpec with BeforeAndAfterAll with ImplicitSender

  )
)
uncaught exception during compilation: scala.reflect.internal.FatalError

scalac: Error: package api does not have a member materializeWeakTypeTag
scala.reflect.internal.FatalError: package api does not have a member materializeWeakTypeTag
    at scala.reflect.internal.Definitions$DefinitionsClass.scala$reflect$internal$Definitions$DefinitionsClass$$fatalMissingSymbol(Definitions.scala:1037)
    at scala.reflect.internal.Definitions$DefinitionsClass.getMember(Definitions.scala:1055)
    at scala.reflect.internal.Definitions$DefinitionsClass.getMemberMethod(Definitions.scala:1090)
    at scala.reflect.internal.Definitions$DefinitionsClass.materializeWeakTypeTag(Definitions.scala:518)
    at scala.tools.reflect.FastTrack$class.fastTrack(FastTrack.scala:34)
    at scala.tools.nsc.Global$$anon$1.fastTrack$lzycompute(Global.scala:493)
    at scala.tools.nsc.Global$$anon$1.fastTrack(Global.scala:493)
    at scala.tools.nsc.typechecker.Namers$Namer.methodSig(Namers.scala:1144)
    at scala.tools.nsc.typechecker.Namers$Namer.getSig$1(Namers.scala:1454)
    at scala.tools.nsc.typechecker.Namers$Namer.typeSig(Namers.scala:1466)
    at scala.tools.nsc.typechecker.Namers$Namer$$anonfun$monoTypeCompleter$1$$anonfun$apply$1.apply$mcV$sp(Namers.scala:731)
    at scala.tools.nsc.typechecker.Namers$Namer$$anonfun$monoTypeCompleter$1$$anonfun$apply$1.apply(Namers.scala:730)
    at scala.tools.nsc.typechecker.Namers$Namer$$anonfun$monoTypeCompleter$1$$anonfun$apply$1.apply(Namers.scala:730)
    at scala.tools.nsc.typechecker.Namers$Namer.scala$tools$nsc$typechecker$Namers$Namer$$logAndValidate(Namers.scala:1499)
    at scala.tools.nsc.typechecker.Namers$Namer$$anonfun$monoTypeCompleter$1.apply(Namers.scala:730)
    at scala.tools.nsc.typechecker.Namers$Namer$$anonfun$monoTypeCompleter$1.apply(Namers.scala:729)
    at scala.tools.nsc.typechecker.Namers$$anon$1.completeImpl(Namers.scala:1614)
...
...

我使用IntelliJ作为ide。有几个scala文件;一个包含一个actor,另一个包含webclient:

package Hub.Subscription

import scala.concurrent.{Promise, Future}
import com.ning.http.client.{AsyncCompletionHandler, AsyncHttpClient, Response}


trait WebClient {
  def postUpdate(url: String, payload: Any, topic: String): Future[Int]
  def postUnSubscribe(url: String, topic: String): Future[Int]
}

case class PostUpdateFailed(status: Int) extends RuntimeException

object AsyncWebClient extends WebClient{

  private val client = new AsyncHttpClient

  override def postUpdate(url: String, payload: Any, topic: String): Future[Int] = {
    val request = client.preparePost(url).build()
    val result = Promise[Int]()
    client.executeRequest(request, new AsyncCompletionHandler[Response]() {
      override def onCompleted(response: Response) = {
        if (response.getStatusCode / 100 < 4)
          result.success(response.getStatusCode)
        else
          result.failure(PostUpdateFailed(response.getStatusCode))
        response
      }

      override def onThrowable(t: Throwable) {
        result.failure(t)
      }
    })
    result.future
  }

  override def postUnSubscribe(url: String, topic: String): Future[Int] = {
    val request = client.preparePost(url).build()
    val result = Promise[Int]
    client.executeRequest(request, new AsyncCompletionHandler[Response] {
      override def onCompleted(response: Response) = {
        if (response.getStatusCode / 100 < 4)
          result.success(response.getStatusCode)
        else
          result.failure(PostUpdateFailed(response.getStatusCode))
        response
      }

      override def onThrowable(t: Throwable) {
        result.failure(t)
      }
    })
    result.future
  }

  def shutdown(): Unit = client.close()
}

我的演员:

package Hub.Subscription

import akka.actor.Actor
import Hub.Subscription.Subscriber.{Failed, Update, UnSubscribe}
import scala.concurrent.ExecutionContext
import java.util.concurrent.Executor

object Subscriber {
  object UnSubscribe
  case class Update(payload: Any)
  case class Failed(callbackUrl: String)
}

class Subscriber(callbackUrl: String, unSubscribeUrl: String, topic: String) extends Actor{

  implicit val executor = context.dispatcher.asInstanceOf[Executor with ExecutionContext]
  def client: WebClient = AsyncWebClient

  def receive = {
    case Update(payload) => doUpdate(payload)
    case UnSubscribe => doUnSubscribe
    case Failed(clientUrl) => //log?
  }

  def doUpdate(payload: Any): Unit = {
    val future = client.postUpdate(callbackUrl, payload, topic)
    future onFailure  {
      case err: Throwable => sender ! Failed(callbackUrl)
    }
  }

  def doUnSubscribe: Unit = {
    //tell the client that they have been un-subscribed
    val future = client.postUnSubscribe(unSubscribeUrl, topic)
    future onFailure {
      case err: Throwable => //log
    }
  }
}

最后我的测试规范:

package Hub.Subscription

import akka.testkit.{ImplicitSender, TestKit}
import akka.actor.{ActorRef, Props, ActorSystem}
import org.scalatest.{WordSpec, BeforeAndAfterAll}
import scala.concurrent.Future
import scala.concurrent.duration._

object SubscriberSpec {

  def buildTestSubscriber(url: String, unSubscribeUrl: String, topic: String, webClient: WebClient): Props =
    Props(new Subscriber(url, unSubscribeUrl, topic) {
      override def client = webClient
    })

  object FakeWebClient extends WebClient {
    override def postUpdate(url: String, payload: Any, topic: String): Future[Int] = Future.successful(201)
    override def postUnSubscribe(url: String, topic: String): Future[Int] = Future.failed(PostUpdateFailed(500))
  }
}

class SubscriberSpec extends TestKit(ActorSystem("SubscriberSpec"))
  with WordSpec
  with BeforeAndAfterAll
  with ImplicitSender {

  import SubscriberSpec._

  "A subscriber" must {

    "forward the update to the callback url" in {
      val fakeClient = FakeWebClient
      val callbackUrl = "http://localhost:9000/UserEvents"
      val subscriber: ActorRef = system.actorOf(buildTestSubscriber(callbackUrl, "unSubscribeUrl", "aTopic", fakeClient))

      subscriber ! Subscriber.Update(Nil)

      within(200 millis) {
        expectNoMsg
      }
    }
  }

  override def afterAll(): Unit = {
    system.shutdown()
  }
}

提前感谢任何帮助/指针!

更新:我应该注意到,如果我不包含测试规范,那么一切都很好。但是当我添加测试规范时,我得到了上面的错误。

1 个答案:

答案 0 :(得分:1)

顺便说一下,我刚刚意识到你正在使用为2.10.0-M4编译的scalatest。

Scala的最终版本不应该与相应的里程碑版本二进制兼容,因此可能会发生奇怪的事情,包括崩溃。

如果您将scalatest的版本更改为"org.scalatest" %% "scalatest" % "1.9.1",一切都会正常工作。