Hi Eric,
I followed your advise and upgraded to Specs2. After rewriting a bunch of matcher it was time to take on the contexts. Eventually I did manage to get things running with the original Specs but decided to try Specs2 and see if the solutions for context would be more elegant. Unfortunately I have not been able to get things running again in Specs2.
Let me first create some context:
Many of my tests require Google Guice to inject them. In the past I have been able to inject the Specification by implementing a GuiceSupport trait that needed the subclass to implement a function providing a Guide Module and a reference to the Spec ('this' from the trait doesn't cut it apparently). The trait would inject the passed reference to the Spec in a 'before' context. This worked but was far from elegant.
Now I have tried something similar with the following:
trait GuiceContext extends Scope { implicit def module2moduleList(mod: AbstractModule): List[AbstractModule] = { mod :: Nil } def module: List[AbstractModule] def target: AnyRef Guice.createInjector(module).injectMembers(target)}And then in the Spec define the following inner class:
class Context extends GuiceContext { @Inject val emailDao: EmailDao = null def module = TestModule def target = this}And then run the example like:
"recognise gmail.com as a valid domain" in new Context { ... }And unfortunately NPEs are the result. The inject code gets called but the 'target' type now turns out to be some odd anonymous class that Guice cannot find annotations on. I thought maybe the fact that it's an inner class has thrown Guice off so I declared as an outer class. Same problems.
I finally did manage to get things working by declaring the injectable val as a member of the Spec and passing it as the target in the context like so:
class BasicEmailDaoSpec extends Specification { @Inject val emailDao: EmailDao = null "The BasicEmailDao" should { "recognise gmail.com as a valid domain" in new Context { emailDao.checkValidity("gmail.com") must beTrue } "reject gnokpokdffr.kwaka as an invalid domain" in new Context { emailDao.checkValidity("gnokpokdffr.kwaka") must beFalse } } class Context extends GuiceContext { def module = TestModule val target = this }}I cannot help but wonder if there are any side effects to using this val declared out of context. Hope you can shed some light on this issue.
Best,
Dirk Louwers