Using JUnit @Rule with ScalaTest (e.g. TemporaryFolder)

I would like to be able to use JUnit rules, such as TemporaryFolder or other TestRule , which we have already developed internally. What is the best method to do this? I know JUnitSuite, but doesn't seem to notice the @Rule annotation. In any case, I would like to use a different set of ScalaTest.

So my questions are:

  • Are JUnit rules supported according to ScalaTest requirements?
  • If not, is there a library that could use it with the Junit TestRule ?
  • If not, how to use the JUnit TestRule in Scala tests?
  • Or is there a more suitable Scala-specific approach for implementing what the TemporaryFolder or, for example, Stefan Birkner System Rules provide?

Here is what I tried using JUnitSuite :

 class MyTest extends JUnitSuite { //@Rule //val temporaryFolder = new TemporaryFolder() // throws java.lang.Exception: The @Rule 'temporaryFolder' must be public. @Rule def temporaryFolder = new TemporaryFolder() @Test def test: Unit = { assert(temporaryFolder.newFile() !== null) // java.lang.IllegalStateException: the temporary folder has not yet been created } } 
+7
scala unit-testing junit scalatest
source share
3 answers

You can solve the problem by creating a member field of type TemporaryFolder and returning that field value using the @Rule function.

 class MyTest extends JUnitSuite { val _temporaryFolder = new TemporaryFolder @Rule def temporaryFolder = _temporaryFolder @Test def test: Unit = { assert(temporaryFolder.newFile() !== null) } } 
+8
source share

Here's what I came up with based on ScalaTest documentation on fixtures . However, I would like to know if there is a better solution.

  • Borrowing method

     class LoanFixtureTest extends FunSuite { def withRule[T <: TestRule](rule: T)(testCode: T => Any): Unit = { rule( new Statement() { override def evaluate(): Unit = testCode(rule) }, Description.createSuiteDescription("JUnit rule wrapper") ).evaluate() } test("my test") { withRule(new TemporaryFolder()) { temporaryFolder => assert(temporaryFolder.newFile() !== null) } } } 
    • Pros: allows you to apply the rule only to tests where necessary.
    • Cons: not very elegant use; uncomfortable when multiple TestRules are required
  • Using stackable mixes with override withFixture(test: NoArgTest)

     trait TemporaryFolderFixture1 extends SuiteMixin { this: Suite => val temporaryFolder = new TemporaryFolder abstract override def withFixture(test: NoArgTest) = { var outcome: Outcome = null val statementBody = () => outcome = super.withFixture(test) temporaryFolder( new Statement() { override def evaluate(): Unit = statementBody() }, Description.createSuiteDescription("JUnit rule wrapper") ).evaluate() outcome } } class StackableTraitFixtureTest extends FunSuite with TemporaryFolderFixture1 { test("my test") { assert(temporaryFolder.newFile() !== null) } } 
    • Pros: very simple use, conveniently allows you to mix several rules in
    • Cons: mixing is required for each rule; rules must be invoked even for tests that they do not need; the rule cannot be used, for example. in BeforeAfterEach#beforeEach()
  • Overriding withFixture(test: OneArgTest)

     trait TemporaryFolderFixture2 { thisFixture: org.scalatest.fixture.FunSuite => type FixtureParam = TemporaryFolder override protected def withFixture(test: OneArgTest): Outcome = { val temporaryFolder = new TemporaryFolder() var outcome: Outcome = null temporaryFolder( new Statement() { override def evaluate(): Unit = { outcome = withFixture(test.toNoArgTest(temporaryFolder)) } }, Description.createSuiteDescription("JUnit rule wrapper") ).evaluate() outcome } } class OneArgWithFixtureTest extends org.scalatest.fixture.FunSuite with TemporaryFolderFixture2 { test("my test") { temporaryFolder => assert(temporaryFolder.newFile() !== null) } } 
    • Cons: only one TestRule allows, which in general works with any rule, and not only with TestRule will require additional effort.

Which one do you like best?

+9
source share

It worked for me. Based on answer . Thus, the annotation will be applied to the (synthetic) getter method

 import org.junit._ import scala.annotation.meta.getter class MyTest extends JUnitSuite { @(Rule @getter) val tempFolder = new TemporaryFolder } 
+1
source share

All Articles