How can I fix the missing implicit value for parameter ta: TildeArrow in a test spec

放肆的年华 提交于 2019-12-18 14:15:41

问题


I'm working on a simple test spec using spray and I can't get it to compile correctly, don't know if I'm doing anything wrong. My version of scala is 2.9.3 and spray 1.0.1 (Updating either of them is not a suitable option). Here's my test spec's code:

import org.specs2.mutable.Specification
import spray.testkit.Specs2RouteTest
import spray.http._
import akka.util.Duration
import java.util.concurrent.TimeUnit

import service.MyProxy

abstract class MyTestSpec extends Specification with Specs2RouteTest with MyProxy{

  val duration = Duration(30, TimeUnit.SECONDS)
  implicit val routeTestTimeout = RouteTestTimeout(duration)

  "MyProxy" should {

    "return a json for GET requests to the /api/getclass/classCode path for a regular request" in {
      Get("/api/getclass/123/") ~> myRoutes~> check {
        responseAs[String] must contain("classCode")
        contentType === ContentTypes.`application/json`
      }
    }

  } // end should...
} //end class

I'm getting this error when I run the test.

[error] C:\Users\Desktop\Project\MyTestSpec.scala:23: could not find implicit value for parameter ta: MyProxySpec.this.TildeArrow[spray.routing.RequestContext,Unit]
[error]       Get("/api/getclass/123/") ~> myRoutes~> check {
[error]                                         ^
[error] one error found
[error] (test:compile) Compilation failed

I've tried different solutions seen on another questions and nothing seems to work so far.

Spray.io: Can't compile test spec

how to make scalatest work with spraytestkit and HttpServiceActor

Basic Spray-Testkit usage to test a route does not work

https://groups.google.com/forum/#!topic/spray-user/H5hkXuDGWYQ

https://groups.google.com/forum/#!topic/spray-user/zFUJSVBPM5c

NOTE: Just for the record, I'm not using scalatest or scalacheck on this. Is purely a [spray] route test.And MyProxy extends Actor


回答1:


I just struggled with this problem. To figure it out, I waded through the Akka HTTP codebase, which is a jungle of implicits.

My problem seemed to be that without the right secondary implicit in place, the correct TildeArrow instance wasn't being found. If you look at the code, the TildeArrow instance, which is required in the error message, is defined as an implicit def injectIntoRoute in the companion object and it requires a whole host of other implicits.

I suggest writing out your code without any of the implicit sugar. This should better help the compiler give you a proper error message:

"MyProxy" should {
  "return a json for GET requests to the /api/getclass/classCode path for a regular request" in {
    val request = Get("/api/getclass/123/")
    val requestWithRoutes = request.~>(myRoutes)(TildeArrow.injectIntoRoute)
    requestWithRoutes.~>(check {
      responseAs[String] must contain("classCode")
      contentType === ContentTypes.`application/json`
    })
  }
}

I think the reason is that since there's no concrete instance of the implicit available, the compiler is trying to satisfy the implicit resolution with the abstract class TildeArrow, and the completely unspecified abstract type, ta.Out, doesn't have a ~> defined.

In my specific case, I was missing an implicit ExecutionContextExecutor, whatever that means.


UPDATE

Actually, I looked into it further and the problem was that I had an implicit def ec: ExecutionContextExecutor declared in my route trait, but trait RouteTest defines its name as executor, and so when I defined my own to fulfill the missing implicit, I ended up with two of the same implicit.

It's a cute API, but the implicit magic is way out of control, IMO, especially given how cryptic the error messages tend to be.




回答2:


The ScalatestRouteTest already provides an implicit ActorySystem. Remove the "implicit" modifier from your actorRefFactory method and the test should get executed.

Spray.io: Can't compile test spec




回答3:


for akka http:

in my case which refer to akka-http-microservice

  • the implicit modifier of executionContext and also need to be removed
  • and should reorder the trait like this : class ServiceSpec extends FlatSpec with Matchers with Service with ScalatestRouteTest



回答4:


In my case, the not found implicit error appeared when in my TestCase I also imported import monix.execution.Scheduler.Implicits.global (which is probably having some sort of ExecutionContext).

I fixed it adding the monix scheduler import just in the method where I needed it, not on the top imports.




回答5:


I can reproduce the precise same error message with Scala 2.10 if myRoutes is not actually a route but a Directive[HNil].

I am therefore guessing that in your unshown service.MyProxy class your route does not complete.

ie

trait MyProxy extends HttpService {
   val myRoutes = path("foo") 
}

Gives this error

trait MyProxy extends HttpService {
  val myRoutes = path("foo") {
   complete(StatusCodes.Accepted)
 }
}

Does not.




回答6:


your build.sbt should have dependencies for akka-stream test along with akka test.

then it should get the whatever dependencies.

refer to this doc:-

scala route test doc




回答7:


To expand a bit on previous answers given, there are some implicits which shouldn't be declared by any other Trait or class that is extends by your Test Class :

  • the ActorSystem
  • the ExecutionContext
  • the DefaultHostInfo (package akka.http.scaladsl.testkit)
  • the ActorMaterializer

if any of these is declared elsewhere than in ScalatestRouteTest, you'll have the following error thrown :

could not find implicit value for parameter ...TildeArrow[RequestContext, SomethingHereOther]


来源:https://stackoverflow.com/questions/28324230/how-can-i-fix-the-missing-implicit-value-for-parameter-ta-tildearrow-in-a-test

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!