Testing Scalatra with Immutable Specs2

import org.specs2.Specification
import org.specs2.mock.Mockito
import org.scalatra.test.ScalatraTests
import org.eclipse.jetty.testing.ServletTester
import org.specs2.specification.After

class MySpec extends Specification { def is = 
  "My spec must" ^
  "verify that scalatra can be tested" ! Specs().assert()

  /**
   * Create a new jetty context each time
   * This lets us mock expectations *per* specification
   */
  case class Specs() extends After with ScalatraTests with Mockito {
    // The servlet tester gives an http context to your tests
    lazy val tester = new ServletTester
    tester.start()

    val myMock = mock[MyObject]

    // Register your servlet with the context and inject the mock
    addServlet(new MyServlet(myMock), "/*")

    // don't leave the jetty context hanging around
    def after { tester.stop() }

    // Pay special attention to the "this" keyword, which will provide the
    // ...method in a scope such that "after" may be called for teardown
    def assert() = this {
      // Just some expectation on the mock object
      myMock.get(0) returns true

      get("/") {
        there was one(myMock).get(0)
      }
    }
  }
}

Comments

Hi,

I think you're misleading the people with this snippet.
This will create a new server instance for ever example you execute. The tester should be started before all examples execute and stop afterwards.

https://github.com/scalatra/scalatra/blob/develop/specs2/src/main/scala/org/scalatra/test/specs2/BaseScalatraSpec.scala#L16

And the way you use this then:
https://github.com/scalatra/scalatra/blob/develop/specs2/src/test/scala/org/scalatra/test/specs2/ScalatraSpecSpec.scala

you can get that by depending on scalatra-specs2
Ben VanEvery said…
Thanks for the pointer. I had some trouble tracking that down in the documentation from the Scalatra Book. The BaseScalatraSpec will simplify my Before and After dependence in my spec.


In regard to creating a new server instance, the Spec that you reference does not get the full idea across of the problem above. Specifically, if your servlet depends on a mock object, then you cannot rely on the same servlet in each test as the injected mock object must be distinct per fragment. I did not originally have this in my code example and will update it to reflect this.

Please correct if I am wrong.

Recent posts