I am transitioning from Java to Scala. I have written a simple test to render a view. Like :
import org.scalatestplus.play.PlaySpec
import org.scalatest._
import org.slf4j.LoggerFactory
import play.test.WithApplication
class EvTemplateTests extends PlaySpec{
implicit lazy val log = LoggerFactory.getLogger(getClass)
//run your test//run your test
"render eval template" in {
val html = views.html.index("Hello")
contentType(html) must equalTo("text/html")
contentAsString(html) must contain("Welcome to Play!")
}
}
When compiling, looks like it is not finding "index","contentType", "contentAsString" etc.Looks like, the project is using the libraries:
lazy val thirdPartyDependencies = Seq(
jdbc,
"com.typesafe.play" %% "anorm" % "2.4.0",
"com.typesafe.play" %% "play-mailer" % "3.0.1",
"com.microsoft.sqlserver" % "mssql-jdbc" % "6.4.0.jre8",
"io.swagger" %% "swagger-play2" % "1.5.0", // This version adds Play 2.4 support.
// ScalaTest+ Play (have to use non-release 1.4.0-M4 version for now as it is only compatible with Play 2.4)
"org.scalatestplus" %% "play" % "1.4.0-M4" % "test",
"org.mockito" % "mockito-core" % "1.10.19" % "test"
)
May I get any insight?
You can start from here:
import controllers.AssetsFinder
import org.specs2.mutable.Specification
import play.api.Application
import play.api.inject.guice.GuiceApplicationBuilder
import play.api.mvc._
import play.api.test._
import play.api.test.Helpers._
class EvTemplateTests
extends Specification
with DefaultAwaitTimeout
with FutureAwaits
with Results {
val application: Application = GuiceApplicationBuilder().build()
"render eval template" in new WithApplication(app = application) {
implicit val assetsFinder = app.injector.instanceOf[AssetsFinder]
val html = views.html.index("Hello")
contentType(html) mustEqual "text/html"
contentAsString(html) must contain("Hello")
}
}
add this after jdbc in LibraryDependencies: specs2 % Test
Most important part of test setup here is implicit AssetFinder that derived from GuiceApplicationBuilder:
val application: Application = GuiceApplicationBuilder().build()
AssetFinder is really important part of view testing in PlayFramework
Related
Im really new to this microservice world and was trying to learn from scratch. But for some reason not able to call a simple dependency.
Getting the error
object twitter is not a member of package com import
com.twitter.finagle._
SBT file, Ive tried three ways
Trial 1
name := "microservicestest"
version := "0.1"
scalaVersion := "2.12.15"
libraryDependencies ++= Seq(
"com.github.finagle" %% "finch-core" % "0.31.0",
"com.github.finagle" %% "finch-circe" % "0.31.0",
"io.circe" %% "circe-generic" % "0.9.0"
)
Trial 2 (puttting just the dependency line in here)
libraryDependencies += "com.twitter" %% "finagle-http" % "21.8.0"
Trial 3
libraryDependencies ++= Seq(
"com.github.finagle" %% "finch-core" % "0.15.1"
)
Scala file
import io.finch._
import com.twitter.finagle.Http
import com.twitter.util.Await
object HelloWorld extends App {
val api: Endpoint[String] = get("hello") { Ok("Hello, World!") }
Await.ready(Http.server.serve(":8080", api.toServiceAs[Text.Plain]))
}
SBT file
libraryDependencies += "com.twitter" %% "finagle-http" % "21.8.0"
Working simple code
import com.twitter.finagle.{Http, Service}
import com.twitter.finagle.http
import com.twitter.util.{Await, Future}
object HelloWorld extends App {
val service = new Service[http.Request, http.Response] {
def apply(req: http.Request): Future[http.Response] =
Future.value(http.Response(req.version, http.Status.Ok))
}
val server = Http.serve(":8080", service)
Await.ready(server)
}
I am running my application with Play Framework(version: 2.2.3), it's giving compilation errors like: not found value anorm and not found value jdbc, I am not sure whether it has connected with my database set up or not ? I have checked the question, but still no use. Please help me that where I am doing wrong ?.
I have done the following:
build.scala:
import sbt._
object AppBuild extends Build {
val appDependencies = Seq(
jdbc,
"com.google.inject" % "guice" % "3.0",
"javax.inject" % "javax.inject" % "1",
"org.postgresql" % "postgresql" % "9.4-1200-jdbc41",
"com.typesafe.play" % "play-iteratees_2.10" % "2.2.3"
)
val main = play.Project(appName, appVersion, appDependencies).settings(
// we can add our own project settings
)
}
app.scala:
package models
import anorm._
import anorm.SqlParser._
import play.api.db.DB
import play.api.db._
import play.api.Play.current
case class Test(id: Pk[Long], content: String)
object Test {
def create(test: Test): Unit = {
DB.withConnection { implicit connection =>
SQL("insert into test(content) values ({content})").on(
'content -> test.content
).executeUpdate()
}
}
}
plugins.sbt:
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.2.3")
app.conf:
db.default.driver=org.postgresql.Driver
db.default.url="jdbc:postgresql://localhost:5432/abcdatabase"
After run i getting this object mongodb is not a member of package com in Play
I cant resolve that problem. Im trying to do Play Scala MongoDB and from client side Scala.js
my build.sbt is >
lazy val server = (project in file("server")).settings(
scalaVersion := scalaV,
scalaJSProjects := clients,
pipelineStages := Seq(scalaJSProd, gzip),
resolvers += "scalaz-bintray" at "https://dl.bintray.com/scalaz/releases",
libraryDependencies ++= Seq(
"com.vmunier" %% "play-scalajs-scripts" % "0.3.0",
"org.mongodb" %% "casbah" % "3.1.0",
"org.webjars" % "jquery" % "1.11.1",
"com.novus" %% "salat" % "1.9.9",
"se.radley" %% "play-plugins-salat" % "1.5.0",
"commons-codec" % "commons-codec" % "1.6",
specs2 % Test
object code
package model
import com.mongodb.DBObject
import com.mongodb.casbah.MongoConnection
import com.mongodb.casbah.commons.MongoDBObject
/**
* Created by qqQQaAs on 2016-01-04.
*/
object AllBooks {
def toJson() {
val collection = MongoConnection()("books")("books")
val query = "Krakow"
// simply convert the result to a string, separating items with a comma
// this string goes inside an "array", and it's ready to hit the road
val json = "[%s]".format(
collection.find(query).toList.mkString(",")
)
}
Controller
package controllers
import com.mongodb.casbah._
import model.AllBooks
import play.api.mvc._
import shared.SharedMessages
object Application extends Controller {
def index = Action {
Ok(views.html.index(SharedMessages.itWorks))
}
def service() = Action {
val json = AllBooks.toJson()
Ok(json).as("application/json")
}
}
Thanks for help guys
You should import the following pages as per the official documentation:
import org.mongodb.scala._
import org.bson._
TL/DR: Checkout last two commits and run sbt clean compile: https://github.com/mirelon/akka-in-action/tree/json/chapter2
There is RestInterface.scala:
package com.goticks
import akka.actor._
import spray.routing._
import spray.http.StatusCodes
import spray.httpx.SprayJsonSupport._
import spray.routing.RequestContext
import akka.util.Timeout
import scala.concurrent.duration._
import scala.language.postfixOps
class RestInterface extends HttpServiceActor
with RestApi {
def receive = runRoute(routes)
}
trait RestApi extends HttpService { actor: Actor =>
import context.dispatcher
import com.goticks.TicketProtocol._
implicit val timeout = Timeout(10 seconds)
import akka.pattern.ask
def routes: Route =
path("events") {
get { requestContext =>
context.actorOf(Props[Resu]).ask(GetEvents)
}
}
}
class Responder(requestContext:RequestContext) extends Actor {
import TicketProtocol._
def receive = {
case Events(events) =>
requestContext.complete(StatusCodes.OK, events)
self ! PoisonPill
}
}
and Resu.scala (note that Resu is alphabetically after RestInterface)
package com.goticks
import akka.actor.Actor
class Resu extends Actor {
import TicketProtocol._
import spray.json._
def receive = {
case GetEvents => {
println(Event(event = "E").toJson)
}
}
}
object TicketProtocol {
import spray.json._
case class Event(event:String)
case object GetEvents
case class Events(events:List[Event])
object Event extends DefaultJsonProtocol {
implicit val format = jsonFormat1(Event.apply)
}
}
build.sbt:
name := "goticks"
version := "0.1-SNAPSHOT"
organization := "com.goticks"
scalaVersion := "2.11.1"
libraryDependencies ++= {
val akkaVersion = "2.3.4"
val sprayVersion = "1.3.1"
Seq(
"com.typesafe.akka" %% "akka-actor" % akkaVersion,
"io.spray" %% "spray-can" % sprayVersion,
"io.spray" %% "spray-routing" % sprayVersion,
"io.spray" %% "spray-json" % "1.2.6"
)
}
build.properties;
sbt.version=0.13.7
plugins.sbt:
resolvers += Classpaths.typesafeResolver
resolvers += "sbt-idea" at "http://mpeltonen.github.com/maven/"
addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.6.0")
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.11.2")
addSbtPlugin("com.typesafe.sbt" % "sbt-start-script" % "0.10.0")
addSbtPlugin("com.typesafe.sbt" % "sbt-multi-jvm" % "0.3.8")
Compilation issue
When I run sbt clean compile, everything is ok. But when I refactor the Resu class into Ress (note that Ress is alphabetically before RestInterface) (also rename its file, the diff can be viewed here: https://github.com/mirelon/akka-in-action/commit/583ca801fb7d1564024eee2f98d57f03ecacc6e5), then there is a compilation error:
[error] /home/miso/IdeaProjects/akka-in-action/chapter2/src/main/scala/com/goticks/Ress.scala:12: Cannot find JsonWriter or JsonFormat type class for com.goticks.TicketProtocol.Event
[error] println(Event(event = "E").toJson)
[error] ^
[error] one error found
[error] (compile:compile) Compilation failed
Clearly there is an implicit json writer missing. Could it be due to incorrect order of compiling? Could sbt compile the classes in alphabetical order, ignoring imports?
Yes, sbt always compiles in alphabetical order. The issue is sbt has no idea the dependencies between files until it runs the compiler.
What you're seeing is the scala compiler itself is dependent on the ordering of source files. Sbt always sorts source files so you can at least work around these issues by placing code in an ordering that works.
I'm not 100% sure why you're hitting such an issue from some implicits + macro hackery, but that could be wrong.
Is there any way to set up IntelliJ's JUnit "Run All Tests" command to automatically pick up Scala Specs2? i.e. removing the boilerplate annotation in this snippet:
#RunWith(classOf[JUnitRunner])
class MySpec extends Specification
It's very irritating to have to remember to add this.
I've seen SpecificationWithJUnit but that is also a bit of a hack (and is incompatible with TestKit). I'm looking for a maven/sbt/intelliJ side solution.
With Intellij, you shouldn't need the annotation to execute your specifications, because it has its own specs2 runner. I'm using IntelliJ 123.100 with a recent version of the Scala plugin (82 I think) and things work ok (except for this issue).
Use #RunWith(classOf[JUnitPlatform]) instead JUnitRunner
Maybe this could help you:
import org.junit.jupiter.api.{DisplayName, Test}
import org.junit.platform.runner.JUnitPlatform
import org.junit.runner.RunWith
import org.scalatest.{BeforeAndAfterAll, Matchers}
import org.scalatest.junit.JUnitSuite
#RunWith(classOf[JUnitPlatform])
class Junit5Test extends JUnitSuite with Matchers with BeforeAndAfterAll {
override def beforeAll: Unit = { println(">>> beforeAll <<< ") }
#Test
#DisplayName("Example with JUnitSuite")
#throws(classOf[RuntimeException])
def throwsExceptionWhenCalled() {
println("Запуск теста...")
assertThrows[RuntimeException] { throw new RuntimeException }
}
}
And build.sbt file:
val junitJupiter = "5.2.0"
val junitPlatform = "1.2.0"
libraryDependencies ++= Seq(
"junit" % "junit" % "4.12" % Test,
"org.junit.jupiter" % "junit-jupiter-api" % junitJupiter % Test,
"org.junit.jupiter" % "junit-jupiter-engine" % junitJupiter % Test,
"org.junit.jupiter" % "junit-jupiter-params" % junitJupiter % Test,
"org.junit.platform" % "junit-platform-launcher" % junitPlatform % Test,
"org.junit.platform" % "junit-platform-engine" % junitPlatform % Test,
"org.junit.platform" % "junit-platform-runner" % junitPlatform % Test,
)