问题
I would like to be able to use JUnit rules such as TemporaryFolder
or other TestRule
s we have already developed in-house.
What is the best method to accomplish that? I'm aware of JUnitSuite but it doesn't seem to pick up the @Rule
annotation.
I would like to use a different ScalaTest suite anyway.
So my questions are:
- Are JUnit rules supported by a ScalaTest suit?
- If not, is there a library out there which would make using Junit
TestRule
s possible? - If not, how to use JUnit
TestRule
s in Scala tests? - Or is there a more appropriate Scala-specific approach for acomplishing what
TemporaryFolder
, or, e.g., Stefan Birkner's System Rules provide?
Here's what I tried with 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
}
}
回答1:
You could solve the problem by creating a member field of type TemporaryFolder
and returning this field value by the @Rule
function.
class MyTest extends JUnitSuite {
val _temporaryFolder = new TemporaryFolder
@Rule
def temporaryFolder = _temporaryFolder
@Test
def test: Unit = {
assert(temporaryFolder.newFile() !== null)
}
}
回答2:
Here is what I came up based on ScalaTest's documentation on fixtures. Still, I would like to know if there is a better solution.
Loan-fixture 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 applying the rule only to tests where it is needed
- Cons: not very elegant usage; clumsy when multiple TestRules are required
Using stackable mixins with
withFixture(test: NoArgTest)
overridetrait 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 usage, conveniently allows mixing multiple rules in
- Cons: requires having a mixin for every rule; rules need to be invoked even for tests that don't need them; rule cannot be used e.g. 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: allows only one TestRule, making in generic to work with any rule instead of just TestRule would require an extra effort
Which one do you like the best?
回答3:
This worked for me. Based on answer. So annotation will be applied to to the (synthetic) getter method
import org.junit._
import scala.annotation.meta.getter
class MyTest extends JUnitSuite {
@(Rule @getter)
val tempFolder = new TemporaryFolder
}
Just make sure to use junit version >4.11.
来源:https://stackoverflow.com/questions/32160549/using-junit-rule-with-scalatest-e-g-temporaryfolder