Alternative of OneAppPerSuite in specs2 scala testing - scala

I am writing unit test cases using specs2 and my application is started and stopped for each test instances.
import org.specs2.mutable._
class HelloWorldSpec extends Specification {
"The 'Hello world' string" should {
"contain 11 characters" in new WithApplication {
"Hello world" must have size(11)
}
"start with 'Hello'" in new WithApplication {
"Hello world" must startWith("Hello")
}
"end with 'world'" in new WithApplication {
"Hello world" must endWith("world")
}
}
}
As mentioned in the documentation for each test case application is started and stopped.
I have found a workaround from the link. Application initializes only once (I haven' tested it yet) for each Test Class.
import org.specs2.mutable._
class HelloWorldSpec extends Specification {sequential
step(Play.start(App)) //supposedly App is iniatilized
"The 'Hello world' string" should {
"contain 11 characters" in {
"Hello world" must have size(11)
}
"start with 'Hello'" in {
"Hello world" must startWith("Hello")
}
"end with 'world'" in {
"Hello world" must endWith("world")
}
}
step(Play.stop())
}
But what if we have multiple classes and we want a single start and stop of the app.
import org.specs2.mutable._
class HelloWorldSpec extends Specification {sequential
step(Play.start(App)) //supposedly App is iniatilized
"The 'Hello world' string" should {
"contain 11 characters" in {
"Hello world" must have size(11)
}
"start with 'Hello'" in {
"Hello world" must startWith("Hello")
}
"end with 'world'" in {
"Hello world" must endWith("world")
}
}
step(Play.stop())
}
import org.specs2.mutable._
class HitchHikerSpec extends Specification {sequential
step(Play.start(App)) //supposedly App is iniatilized
"The 'Hitch Hiker' string" should {
"contain 11 characters" in {
"Hitch Hiker" must have size(11)
}
"start with 'Hitch'" in {
"Hitch Hiker" must startWith("Hitch")
}
"end with 'Hiker'" in {
"Hitch Hiker" must endWith("Hiker")
}
}
step(Play.stop())
}
How would I start and stop app for once?
There is a similar solution implemented in scalatest using OneAppPerSuite.
Here is the link and example.
import play.api.test._
import org.scalatest._
import org.scalatestplus.play._
import play.api.{Play, Application}
import play.api.inject.guice._
// This is the "master" suite
class NestedExampleSpec extends Suites(
new OneSpec,
new TwoSpec,
new RedSpec,
new BlueSpec
) with OneAppPerSuite {
// Override app if you need an Application with other than non-default parameters.
implicit override lazy val app: Application =
new GuiceApplicationBuilder().configure(Map("ehcacheplugin" -> "disabled")).build()
}
// These are the nested suites
#DoNotDiscover class OneSpec extends PlaySpec with ConfiguredApp
#DoNotDiscover class TwoSpec extends PlaySpec with ConfiguredApp
#DoNotDiscover class RedSpec extends PlaySpec with ConfiguredApp
#DoNotDiscover
class BlueSpec extends PlaySpec with ConfiguredApp {
"The OneAppPerSuite trait" must {
"provide an Application" in {
app.configuration.getString("ehcacheplugin") mustBe Some("disabled")
}
"make the Application available implicitly" in {
def getConfig(key: String)(implicit app: Application) = app.configuration.getString(key)
getConfig("ehcacheplugin") mustBe Some("disabled")
}
"start the Application" in {
Play.maybeApplication mustBe Some(app)
}
}
}
Can something similar be implemented in specs2?

With specs2 you can do something similar with specification references:
class SuiteSpec extends Specification { def is = s2"""
${link(StartSpec).hide}
${ "first spec" ~ new Spec1Spec }
${ "second spec" ~ new Spec2Spec }
${link(StopSpec).hide}
"""
}
object StartSpec extends Specification { def is = s2"""
${step(println("start"))}
"""
}
class Spec1Spec extends Specification { def is = s2"""
example1 $e1
"""
def e1 = { println("example1"); ok }
}
class Spec2Spec extends Specification { def is = s2"""
example2 $e2
"""
def e2 = { println("example2"); ok }
}
object StopSpec extends Specification { def is = s2"""
${step(println("stop"))}
"""
}
Then if you run:
testOnly *Suite* -- all
You should see the following lines printed out:
start
example1
example2
stop

Related

How to run a method before all test in word spec like unit test?

How can I run a before method with word spec like in scala?
I have this code, but the before method is not executing before my test:
class SomeClassTest extends TestKit(ActorSystem("test", ConfigFactory.empty())) with WordSpecLike with MockitoSugar with BeforeAndAfter {
override protected def before(fun: => Any): Unit = {
//some code ...
}
"A SomeClass" must {
"blah blah blah" in {
//some code...
}
}
}
You don't have to actually override before in SomeClassTest, but instead call it passing a function with test setup code:
class SomeClassTest extends TestKit(ActorSystem("test", ConfigFactory.empty())) with WordSpecLike with MockitoSugar with BeforeAndAfter {
before {
//some code ...
}
"A SomeClass" must {
"blah blah blah" in {
//some code...
}
}
}

My Play Application's Constructor takes an argument, how do I give a mocked argument at Spec Test?

If my play application has something like this:
class Foo() extends Bar {}
class Application #Inject (f: Foo) extends Controller {
def index = Action { OK("Hi, Foo App") }
}
How do I change my spec test to accept MockedFoo class?
#RunWith(classOf[JUnitRunner])
class MockedFoo() extends Bar {}
class ApplicationTest(implicit ee: ExecutionEnv) extends Specification {
"Sending a GET request to index " should {
"Respond with OK " in new WithApplication { //######## Inject MockedFoo
val response = route(app, FakeRequest(GET, "/")).get
status(response) mustEqual OK
}
}
}
Thanks for the help:
Copying from my own Gist: https://gist.github.com/rethab/01fde763d10f29273d43
First, create a helper class for convenience:
class WithFancyApp(lang: Lang = Lang.defaultLang,
overrideModules: Seq[GuiceableModule] = Seq()) extends
WithApplication(
app =
new GuiceApplicationBuilder()
.in(Environment(new File("."), getClass.getClassLoader, Mode.Test))
.loadConfig(env => Configuration.load(env))
.overrides(overrideModules:_*)
.bindings()
.build
) {
implicit def messages: Messages = Messages(lang, app.injector.instanceOf[MessagesApi])
}
Usage:
"use the overridden bindigs" in new WithFancyApp(
overrideModules = Seq(bind[MyInterface].to[MyImplementation])
) {
// test stuff with all regular bindings plus the ones from above
}

Reuse mock declaration across tests

I'd like to reuse mock declarations accross tests (if possible).
Here is a minimal non-working example using ScalaTest and Mockito. I'm expecting the ​yes​ value in the first test but I get the ​other​ value.
It seems that the latest Mockito.when is the one applied for all test clauses.
Is there a way to avoid declaring mocks in each in clause?
import org.mockito.Mockito._
import org.scalatest.mock.MockitoSugar
import org.scalatest.{Matchers, WordSpec}
​
class ReuseMocksSpec extends WordSpec with Matchers with MockitoSugar {
"A test" when {
val service = mock[Service]
"sharing mocks among tests" should {
when(service.getVal).thenReturn("yes")
"get yes value" in {
service.getVal should be("yes")
}
}
"sharing mocks among other tests" should {
when(service.getVal).thenReturn("other")
"get other value" in {
service.getVal should be("other")
}
}
}
​
trait Service {
def getVal: String
}
}
I reviewed the way I designed it and am now using a function to build my mocks:
def withValue(value: String)(body: (Service => String)) = {
val service = mock[Service]
when(service.getVal).thenReturn(value)
body(service)
}
The test class would become:
import org.mockito.Mockito._
import org.scalatest.mock.MockitoSugar
import org.scalatest.{Matchers, WordSpec}
class ReuseMocksSpec extends WordSpec with Matchers with MockitoSugar {
"A test" when {
"sharing mocks among tests" should {
"get yes value" in {
val value = withValue("yes") { service =>
service.getVal
}
value should be("yes")
}
}
"sharing mocks among other tests" should {
"get other value" in {
val value = withValue("other") { service =>
service.getVal
}
value should be("other")
}
}
}
def withValue(value: String)(body: (Service => String)) = {
val service = mock[Service]
when(service.getVal).thenReturn(value)
body(service)
}
trait Service {
def getVal: String
}
}
I don't know if it's the cleanest and easiest way to do it but it works...

Specs2 with Scaldi - wrong implicit injector being invoked

I'm trying to run a test with scaldi and specs2. In the test I need to override a StringManipulator function that uses an injected ProxyManipulator. The ProxyManipulator takes a string and returns its upper case in a Future. The replacement manipulator in the test returns a Future("Test Message").
Here is the StringManipulator class where the injection occurs:
class StringManipulator {
def manip (str : String) (implicit inj: Injector) : String = {
val prox = inject[ProxyManipulator]
Await.result(prox.manipulate(str), 1 second)
}
}
I'm using a package.object that contains the implicit injector:
import modules.MyModule
package object controllers {
implicit val appModule = new MyModule
}
And here is the specs2 test with the new binding:
#RunWith(classOf[JUnitRunner])
class StringManipScaldiSpec extends Specification {
class TestModule extends Module {
bind [ProxyManipulator] to new ProxyManipulator {
override def manipulate(name: String) = Future("Test Message")
}
}
"Application" should {
"do something" in {
val myTestModule = new TestModule
val str = "my string"
val stringMan = new StringManipulator() //(myTestModule)
stringMan.manip(str)(myTestModule) === "Test Message"
}
}
}
The problem is that when the test runs the class StringManipulator is still using the original Proxy Manipulator instead of the one passed in the TestModule. Any ideas?

How can I skip a "should" block/fragment in specs2?

Suppose I have a specs2 specification defined in the "unit" style as follows:
import org.specs2.mutable
class MyClassSpec extends mutable.Specification {
"myMethod" should {
"return positive values" in {
MyClass.myMethod must beGreaterThan(0)
}
"return values less than 100" in {
MyClass.myMethod must beLessThan(100)
}
}
}
Is there an easy way to skip/disable/mark pending all of the examples within the should block/fragment for myMethod?
Obviously I can call pendingUntilFixed or return pending from each individual example in the block, but this would be rather tedious for a block with many specifications.
It seems like this would be a common occurrence if MyClass.myMethod is difficult to implement and gets punted. Is there another way that this is commonly done in specs2?
You can mix in the Tags trait and define any section you want:
import org.specs2.mutable._
class MyClassSpec extends Specification with Tags {
section("pending")
"myMethod" should {
"return positive values" in {
MyClass.myMethod must beGreaterThan(0)
}
"return values less than 100" in {
MyClass.myMethod must beLessThan(100)
}
}
section("pending")
}
Then you run your specification with exclude pending
>test-only *MyClassSpec* -- exclude pending
This is documented here.
You can also use an implicit context to make sure that all your examples in the should block are PendingUntilFixed:
import org.specs2._
import execute._
class MyClassSpec extends mutable.Specification {
"this doesn't work for now" >> {
implicit val puf = pendingContext("FIXME")
"ex1" in ko
"ex2" in ok
}
"but this works ok" >> {
"ex3" in ko // maybe not here ;-)
"ex4" in ok
}
def pendingContext(reason: String) = new mutable.Around {
def around[T <% Result](t: =>T) =
t.pendingUntilFixed(reason)
}
}
Update for specs2 3.x
import org.specs2._
import execute._
class TestMutableSpec extends mutable.Specification {
"this doesn't work for now" >> {
implicit def context[T] = pendingContext[T]("FIXME")
"ex1" in ko
"ex2" in ok
}
"but this works ok" >> {
"ex3" in ko // maybe not here ;-)
"ex4" in ok
}
def pendingContext[T](reason: String): AsResult[MatchResult[T]] =
new AsResult[MatchResult[T]] {
def asResult(t: =>MatchResult[T]): Result =
AsResult(t).pendingUntilFixed(reason)
}
}