testing spray.io
in 45 minutes
The Plan
● What spray is
● What we are testing
● How
Spray
“an open-source toolkit for building
REST/HTTP-based integration layers on top of
Scala and Akka”
Spray
“an open-source toolkit for building
REST/HTTP-based integration layers on top of
Scala and Akka”
Library to wrap services with REST API
REST API
● request routing
● (un)marshalling to / from domain objects
● authentication / authorization
● encoding / decoding (compression)
● serving static content
● caching
REST API
● request routing - headers, params and paths
● (un)marshalling to / from domain objects - req/resp entity
● authentication / authorization - directives
● encoding / decoding (compression) - Gzip, Deflate
● serving static content - the same way as request routing
● caching - some of
Example
libraryDependencies ++= {
val akkaV = "2.3.7"
val sprayV = "1.3.2"
Seq(
"com.typesafe.akka" %% "akka-actor" % akkaV,
"io.spray" %% "spray-can" % sprayV,
"io.spray" %% "spray-routing" % sprayV,
"io.spray" %% "spray-testkit" % sprayV % "test",
"org.scalatest" %% "scalatest" % "2.2.4" % "test")
}
Example
import scala.concurrent.duration._
import akka.actor.{Props, ActorSystem}
import akka.io.IO
import akka.pattern.ask
import akka.util.Timeout
import spray.can.Http
object App extends scala.App {
implicit val system = ActorSystem("system")
val service = system.actorOf( Props(new RestService), "rest")
implicit val timeout = Timeout(5.seconds)
IO(Http) ? Http.Bind(service, interface = "localhost", port = 8080)
}
Example - not testable
import spray.routing.HttpServiceActor
class RestService extends HttpServiceActor {
def receive = runRoute(route)
def route =
get {
complete( "ok")
}
}
Example - extract trait
import spray.routing.HttpService
trait SimpleService extends HttpService {
def simpleRoute =
get {
complete( "ok")
}
}
Example - replace route
class RestService extends HttpServiceActor
with SimpleService {
def receive = runRoute(route)
def route =
simpleRoute
}
Example - test
import org.scalatest. {Matchers, FlatSpec}
import spray.testkit.ScalatestRouteTest
class SimpleServiceSpec extends FlatSpec with Matchers
with ScalatestRouteTest
with SimpleService {
def actorRefFactory = system // boilerplate
"A SimpleService" should "return 'ok' for GET request on /" in {
Get("/") ~> simpleRoute ~> check {
responseAs[ String] should be ("ok")
}
}
}
Test API
status.intValue
headers
responseAs[T] // (un)marshalling - String for free
rejections // little tricky when want to test deeper
Get("/users?format=pretty" )
Post("/user", """{"name": "pawel"}""" )
Put("/user/1", """{"name": "kopiczko"}""" )
Delete("/user/1")
Get("/mail/all") ~> Authorization(BasicHttpCredentials ("pawel", ""))
Test Rejection
def deleteRoute =
delete {
path("user" / IntNumber) { id =>
userService.delete(id)
complete( "Deleted user with id " + id)
}
}
Get("/user/1") ~> deleteRoute ~> check {
rejection should be ( MethodRejection (HttpMethods.DELETE))
}
OK, but...
Test Rejection
Get("/user/1") ~> deleteRoute ~> check {
status.intValue should be ( 405)
}
[info] - should not allow GET request on /user *** FAILED ***
[info] Request was rejected with List(MethodRejection(DELETE))
Test Rejection
Get("/user/1") ~> {
handleRejections( RejectionHandler .Default) {
deleteRoute
}
} ~> check {
status.intValue should be ( 405)
}
OK
Dependency Injection
Route is a method - pass arguments
def userRoute(service: UserService) =
get("user" / IntNumber) { id =>
complete {
userService.get(id)
}
}
Get("/user/1") ~> userRoute(userServiceMock) ~> check
Dependency Injection
● Test the REST layer responsibility
● Do NOT test underlying services
● There is another place for that
http://www.slideshare.net/kopiczko/scala45-spray-test-45539693
http://goo.gl/YuL3On

More Related Content

PDF
Creating a polyglottestframework
PDF
A dive into akka streams: from the basics to a real-world scenario
PDF
Streaming all the things with akka streams
PDF
visualization of Docker metrics
PDF
Akka streams - Umeå java usergroup
PDF
Async Server Rendering in React+Redux at NYTimes (redux-taxi)
PPTX
동기화 시대를 뛰어넘는 비동기 프로그래밍
PDF
Continous Delivery and Rails Upgrades
Creating a polyglottestframework
A dive into akka streams: from the basics to a real-world scenario
Streaming all the things with akka streams
visualization of Docker metrics
Akka streams - Umeå java usergroup
Async Server Rendering in React+Redux at NYTimes (redux-taxi)
동기화 시대를 뛰어넘는 비동기 프로그래밍
Continous Delivery and Rails Upgrades

What's hot (20)

PDF
Consul presentation
PPTX
Airflow and supervisor
PPTX
Sharding and Load Balancing in Scala - Twitter's Finagle
TXT
Readme
PPTX
Hackathon presentation
PDF
Reactive streams processing using Akka Streams
PDF
Retrofit
PDF
Prometheus meets Consul -- Consul Casual Talks
PDF
Reactive stream processing using Akka streams
PDF
Distributed Eventing in OSGi
PPTX
Advanced Durable Functions - Serverless Meetup Tokyo - Feb 2018
PDF
Appengine Java Night #2 Lt
PPT
Parse Server Open Source
PDF
From Zero to Stream Processing
PPTX
Integration testing for salt states using aws ec2 container service
PDF
Retrofit
PDF
OASGraph LoopBack 4 Integration
PDF
Intelligent infrastructure with SaltStack
PDF
Next generation actors with Akka
PDF
Retrofit library for android
Consul presentation
Airflow and supervisor
Sharding and Load Balancing in Scala - Twitter's Finagle
Readme
Hackathon presentation
Reactive streams processing using Akka Streams
Retrofit
Prometheus meets Consul -- Consul Casual Talks
Reactive stream processing using Akka streams
Distributed Eventing in OSGi
Advanced Durable Functions - Serverless Meetup Tokyo - Feb 2018
Appengine Java Night #2 Lt
Parse Server Open Source
From Zero to Stream Processing
Integration testing for salt states using aws ec2 container service
Retrofit
OASGraph LoopBack 4 Integration
Intelligent infrastructure with SaltStack
Next generation actors with Akka
Retrofit library for android
Ad

Viewers also liked (20)

PPTX
Water repellency & waterproof & repellency test method
PPTX
Water repellency of fabrics
PPTX
Fabric tensile strength test
PPTX
Dunya Paralari Gezgin
PPTX
Consejotecnicoescolarfaseintensiva20152016(2)
PDF
Tema1. Introduccion molinux
PDF
KW Outfront Magazine Online Edition Sept/Oct 2010
PDF
Girsberger Benelux - Office collection
PPTX
CES 2015 - Journée 1 vue par EMOTIC
PDF
AguayoAbogados
DOCX
COMO PUBLICAR ARCHIVOS EN EL BLOG
PPT
U4 jou231 mobile_message
PDF
Dragonslayer weekly update 17 aug 12
PPTX
Taskhero deck 10.15.12
PDF
Programa #llopasfera14
PPTX
BB Family FB Group _ Jul -15-2010
PPTX
Angola cessaf final_2-3-2013
PDF
Q7 es - Iniciativas locales de impulso a la innovación empresarial (ES)
PDF
06 10-14 - acta pleno nº 16
PDF
Bomba Dosadora Mroy
Water repellency & waterproof & repellency test method
Water repellency of fabrics
Fabric tensile strength test
Dunya Paralari Gezgin
Consejotecnicoescolarfaseintensiva20152016(2)
Tema1. Introduccion molinux
KW Outfront Magazine Online Edition Sept/Oct 2010
Girsberger Benelux - Office collection
CES 2015 - Journée 1 vue par EMOTIC
AguayoAbogados
COMO PUBLICAR ARCHIVOS EN EL BLOG
U4 jou231 mobile_message
Dragonslayer weekly update 17 aug 12
Taskhero deck 10.15.12
Programa #llopasfera14
BB Family FB Group _ Jul -15-2010
Angola cessaf final_2-3-2013
Q7 es - Iniciativas locales de impulso a la innovación empresarial (ES)
06 10-14 - acta pleno nº 16
Bomba Dosadora Mroy
Ad

Similar to Scala45 spray test (20)

PDF
Building scalable rest service using Akka HTTP
PDF
JAX-RS.next
PPT
Developing RESTful WebServices using Jersey
PDF
scalaphx-akka-http
PDF
Federico Feroldi - Scala microservices
KEY
Using and scaling Rack and Rack-based middleware
PDF
Server Side Swift: Vapor
PPTX
StackMate - CloudFormation for CloudStack
PDF
Spray human talks
PDF
[245] presto 내부구조 파헤치기
PDF
Java colombo-deep-dive-into-jax-rs
KEY
How and why i roll my own node.js framework
PDF
Angular for Java Enterprise Developers: Oracle Code One 2018
PDF
PDF
Java-Jersey 到 Python-Flask 服務不中斷重構之旅
PDF
Elasticsearch And Ruby [RuPy2012]
ODP
Nexthink Library - replacing a ruby on rails application with Scala and Spray
PPTX
Resthub lyonjug
PDF
Rack
PDF
GraphQL API in Clojure
Building scalable rest service using Akka HTTP
JAX-RS.next
Developing RESTful WebServices using Jersey
scalaphx-akka-http
Federico Feroldi - Scala microservices
Using and scaling Rack and Rack-based middleware
Server Side Swift: Vapor
StackMate - CloudFormation for CloudStack
Spray human talks
[245] presto 내부구조 파헤치기
Java colombo-deep-dive-into-jax-rs
How and why i roll my own node.js framework
Angular for Java Enterprise Developers: Oracle Code One 2018
Java-Jersey 到 Python-Flask 服務不中斷重構之旅
Elasticsearch And Ruby [RuPy2012]
Nexthink Library - replacing a ruby on rails application with Scala and Spray
Resthub lyonjug
Rack
GraphQL API in Clojure

Recently uploaded (20)

PDF
AI-Powered Threat Modeling: The Future of Cybersecurity by Arun Kumar Elengov...
PDF
MCP Security Tutorial - Beginner to Advanced
PPTX
Tech Workshop Escape Room Tech Workshop
PPTX
Cybersecurity-and-Fraud-Protecting-Your-Digital-Life.pptx
PDF
AI/ML Infra Meetup | LLM Agents and Implementation Challenges
PDF
AI Guide for Business Growth - Arna Softech
PDF
Introduction to Ragic - #1 No Code Tool For Digitalizing Your Business Proces...
PDF
DuckDuckGo Private Browser Premium APK for Android Crack Latest 2025
DOCX
Modern SharePoint Intranet Templates That Boost Employee Engagement in 2025.docx
PDF
Multiverse AI Review 2025: Access All TOP AI Model-Versions!
PPTX
MLforCyber_MLDataSetsandFeatures_Presentation.pptx
PDF
Wondershare Recoverit Full Crack New Version (Latest 2025)
PDF
AI/ML Infra Meetup | Beyond S3's Basics: Architecting for AI-Native Data Access
PDF
DNT Brochure 2025 – ISV Solutions @ D365
PPTX
Python is a high-level, interpreted programming language
PDF
EaseUS PDF Editor Pro 6.2.0.2 Crack with License Key 2025
PPTX
Lecture 5 Software Requirement Engineering
PPTX
Computer Software - Technology and Livelihood Education
PDF
How Tridens DevSecOps Ensures Compliance, Security, and Agility
PPTX
How to Odoo 19 Installation on Ubuntu - CandidRoot
AI-Powered Threat Modeling: The Future of Cybersecurity by Arun Kumar Elengov...
MCP Security Tutorial - Beginner to Advanced
Tech Workshop Escape Room Tech Workshop
Cybersecurity-and-Fraud-Protecting-Your-Digital-Life.pptx
AI/ML Infra Meetup | LLM Agents and Implementation Challenges
AI Guide for Business Growth - Arna Softech
Introduction to Ragic - #1 No Code Tool For Digitalizing Your Business Proces...
DuckDuckGo Private Browser Premium APK for Android Crack Latest 2025
Modern SharePoint Intranet Templates That Boost Employee Engagement in 2025.docx
Multiverse AI Review 2025: Access All TOP AI Model-Versions!
MLforCyber_MLDataSetsandFeatures_Presentation.pptx
Wondershare Recoverit Full Crack New Version (Latest 2025)
AI/ML Infra Meetup | Beyond S3's Basics: Architecting for AI-Native Data Access
DNT Brochure 2025 – ISV Solutions @ D365
Python is a high-level, interpreted programming language
EaseUS PDF Editor Pro 6.2.0.2 Crack with License Key 2025
Lecture 5 Software Requirement Engineering
Computer Software - Technology and Livelihood Education
How Tridens DevSecOps Ensures Compliance, Security, and Agility
How to Odoo 19 Installation on Ubuntu - CandidRoot

Scala45 spray test

  • 2. The Plan ● What spray is ● What we are testing ● How
  • 3. Spray “an open-source toolkit for building REST/HTTP-based integration layers on top of Scala and Akka”
  • 4. Spray “an open-source toolkit for building REST/HTTP-based integration layers on top of Scala and Akka” Library to wrap services with REST API
  • 5. REST API ● request routing ● (un)marshalling to / from domain objects ● authentication / authorization ● encoding / decoding (compression) ● serving static content ● caching
  • 6. REST API ● request routing - headers, params and paths ● (un)marshalling to / from domain objects - req/resp entity ● authentication / authorization - directives ● encoding / decoding (compression) - Gzip, Deflate ● serving static content - the same way as request routing ● caching - some of
  • 7. Example libraryDependencies ++= { val akkaV = "2.3.7" val sprayV = "1.3.2" Seq( "com.typesafe.akka" %% "akka-actor" % akkaV, "io.spray" %% "spray-can" % sprayV, "io.spray" %% "spray-routing" % sprayV, "io.spray" %% "spray-testkit" % sprayV % "test", "org.scalatest" %% "scalatest" % "2.2.4" % "test") }
  • 8. Example import scala.concurrent.duration._ import akka.actor.{Props, ActorSystem} import akka.io.IO import akka.pattern.ask import akka.util.Timeout import spray.can.Http object App extends scala.App { implicit val system = ActorSystem("system") val service = system.actorOf( Props(new RestService), "rest") implicit val timeout = Timeout(5.seconds) IO(Http) ? Http.Bind(service, interface = "localhost", port = 8080) }
  • 9. Example - not testable import spray.routing.HttpServiceActor class RestService extends HttpServiceActor { def receive = runRoute(route) def route = get { complete( "ok") } }
  • 10. Example - extract trait import spray.routing.HttpService trait SimpleService extends HttpService { def simpleRoute = get { complete( "ok") } }
  • 11. Example - replace route class RestService extends HttpServiceActor with SimpleService { def receive = runRoute(route) def route = simpleRoute }
  • 12. Example - test import org.scalatest. {Matchers, FlatSpec} import spray.testkit.ScalatestRouteTest class SimpleServiceSpec extends FlatSpec with Matchers with ScalatestRouteTest with SimpleService { def actorRefFactory = system // boilerplate "A SimpleService" should "return 'ok' for GET request on /" in { Get("/") ~> simpleRoute ~> check { responseAs[ String] should be ("ok") } } }
  • 13. Test API status.intValue headers responseAs[T] // (un)marshalling - String for free rejections // little tricky when want to test deeper Get("/users?format=pretty" ) Post("/user", """{"name": "pawel"}""" ) Put("/user/1", """{"name": "kopiczko"}""" ) Delete("/user/1") Get("/mail/all") ~> Authorization(BasicHttpCredentials ("pawel", ""))
  • 14. Test Rejection def deleteRoute = delete { path("user" / IntNumber) { id => userService.delete(id) complete( "Deleted user with id " + id) } } Get("/user/1") ~> deleteRoute ~> check { rejection should be ( MethodRejection (HttpMethods.DELETE)) } OK, but...
  • 15. Test Rejection Get("/user/1") ~> deleteRoute ~> check { status.intValue should be ( 405) } [info] - should not allow GET request on /user *** FAILED *** [info] Request was rejected with List(MethodRejection(DELETE))
  • 16. Test Rejection Get("/user/1") ~> { handleRejections( RejectionHandler .Default) { deleteRoute } } ~> check { status.intValue should be ( 405) } OK
  • 17. Dependency Injection Route is a method - pass arguments def userRoute(service: UserService) = get("user" / IntNumber) { id => complete { userService.get(id) } } Get("/user/1") ~> userRoute(userServiceMock) ~> check
  • 18. Dependency Injection ● Test the REST layer responsibility ● Do NOT test underlying services ● There is another place for that