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

Scala编译器错误:包api没有成员MaterializeWakTypeTag,scala,intellij-idea,akka,scalatest,Scala,Intellij Idea,Akka,Scalatest,我是scala的新手,所以我准备接受我做错了什么 我正在和Akka玩,并使用scalatest和Akka测试套件进行测试。这是我的build.sbt配置 name := """EventHub""" version := "1.0" scalaVersion := "2.10.3" libraryDependencies ++= Seq( "com.typesafe.akka" % "akka-actor_2.10" % "2.2.3", "com.typesafe.akka" %

我是scala的新手,所以我准备接受我做错了什么

我正在和Akka玩,并使用scalatest和Akka测试套件进行测试。这是我的build.sbt配置

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编译器问题和bug。我不知道这是我看到的还是我在某处犯了一个基本的错误。以下是输出的摘要(为了简洁起见,我删除了很多“噪音”;如果需要,可以添加更多细节!):

以及:

我使用IntelliJ作为ide。有几个scala文件;一个包含参与者,另一个包含网络客户端:

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.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()
  }
}
提前感谢您的帮助/指点


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

顺便说一句,我刚刚意识到您使用的是为2.10.0-M4编译的scalatest

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


如果将scalatest的版本更改为
“org.scalatest”%%“scalatest”%%“1.9.1”
,一切都会正常运行。

因此,在重新编写测试以使用Specs2而不是scalatest之后,我可以让它进行编译。但是,我仍然很想知道为什么我会看到这些编译器错误。。。!听起来好像scalatest的宏有问题。现在开始调查。你能把你的项目上传到github吗?使用您提供的文件编译时遇到问题。事实上,这比宏实现中的问题更深层次……结果比我想象的要简单:)太好了-这就解决了它!谢谢
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()
  }
}