Skip to content

Instantly share code, notes, and snippets.

@tifletcher
Created December 22, 2017 22:39
Show Gist options
  • Save tifletcher/cf31570e9bccf5f4677c8695e93cfd80 to your computer and use it in GitHub Desktop.
Save tifletcher/cf31570e9bccf5f4677c8695e93cfd80 to your computer and use it in GitHub Desktop.
Using locally defined traits for per-test state setup with scalatest. Much NIH.
import org.scalatest.FunSpec
class ScopedSpec extends FunSpec {
trait SpecScope {
val x = 1
}
implicit val scopeConstructor = ScopeFactory(new SpecScope {})
// or, without the aid of the ScopeFactory.apply:
// implicit object SpecScopeFactory extends ScopeFactory[SpecScope] {
// override def apply: SpecScope = new SpecScope {}
// }
describe("scope helper") {
it("must be able to create new default scopes") {
using[SpecScope]() { scope =>
assert(scope.x == 1)
}
}
it("must be able to use explicitly overridden scopes") {
val s2 = new SpecScope {
override val x = 2
}
using(s2) { scope =>
assert(scope.x == 2)
}
}
it("can have scopes imported for a different feel")(using[SpecScope]() { scope =>
import scope._
assert(x == 1)
})
}
// machinery. these go in a helper namespace somewhere
trait ScopeFactory[T] {
def apply: T
}
// optional. allows implicit creation as implicit val foo = ScopeFactory(new ScopeFactory{})
object ScopeFactory {
def apply[T](constructor: => T): ScopeFactory[T] = new ScopeFactory[T] {
def apply = constructor
}
}
def using[T: ScopeFactory](scope: Option[T] = None)(block: T => Unit): Unit = scope match {
case Some(s) => block(s)
case _ =>
val scope = implicitly[ScopeFactory[T]].apply
block(scope)
}
def using[T: ScopeFactory](scope: T)(block: T => Unit): Unit = using[T](Some(scope))(block)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment