shmish111
shmish111

Reputation: 3797

Scalatest sharing service instance across multiple test suites

I have FlatSpec test classes which need to make use of a REST service for some fixture data. When running all the tests in one go I only really want to instantiate the REST client once as it may be quite expensive. How can I go about this and can I also get it to work for running just one test class when I am running in my IDE?

Upvotes: 5

Views: 2044

Answers (2)

arpad
arpad

Reputation: 422

Pawel's last comment fits well. It was easier by inheriting from Suite with BeforaAndAfterAll instead of Suites.

import com.typesafe.config.ConfigFactory
import com.google.inject.Guice
import org.scalatest.{BeforeAndAfterAll, Suite}
import net.codingwell.scalaguice.InjectorExtensions.ScalaInjector

class EndToEndSuite extends Suite with BeforeAndAfterAll {

    private val injector = {
        val config = ConfigFactory.load
        val module = new AppModule(config) // your module here
        new ScalaInjector(Guice.createInjector(module))
    }

    override def afterAll {
        // your shutdown if needed
    }

    override val nestedSuites = collection.immutable.IndexedSeq(
        injector.instance[YourTest1],
        injector.instance[YourTest2] //...
    )
}

Upvotes: 2

pawel.panasewicz
pawel.panasewicz

Reputation: 1833

1. Use mocking:

I would advice you to use some kind of mocking when you try to test REST service. You can try for example scala-mock. Creation of mock service isn't time/cpu consuming, so you can create mocks in all your tests and don't need to share them. Look:

trait MyRestService {
  def get(): String
}

class MyOtherService(val myRestService: MyRestService) {
  def addParentheses = s"""(${myRestService.getClass()})"""
}

import org.scalamock.scalatest.MockFactory

class MySpec extends FreeSpec with MockFactory {

  "test1 " in {
    // create mock rest service and define it's behaviour
    val myRestService = mock[MyRestService]
    val myOtherService = new MyOtherService(myRestService)
    inAnyOrder {
      (myRestService.get _).expects().returning("ABC")
    }

    //now it's ready, you can use it
    assert(myOtherService.addParentheses === "(ABC)")
  }
}

2. Or use Sharing fixtures:

If you still want to use real implementation of you REST service and create only one instance and then share it with some test condider using:

  • get-fixture methods => Use it when you need the same mutable fixture objects in multiple tests, and don't need to clean up after.

  • withFixture(OneArgTest) => Use when all or most tests need the same fixtures that must be cleaned up afterwords.

Refer to http://www.scalatest.org/user_guide/sharing_fixtures#loanFixtureMethods for more details and code examples.

If you want to share the same fixture against multiple Suites use org.scalatest.Suites and @DoNotDiscover annotation (these requires at least scalatest-2.0.RC1)

Upvotes: 2

Related Questions