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

后端 未结 3 439
温柔的废话
温柔的废话 2020-12-20 12:09

I would like to be able to use JUnit rules such as TemporaryFolder or other TestRules we have already developed in-house. What is the best method

相关标签:
3条回答
  • 2020-12-20 12:26

    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)
      }
    }
    
    0 讨论(0)
  • 2020-12-20 12:31

    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.

    1. 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
    2. Using stackable mixins with withFixture(test: NoArgTest) override

      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 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()
    3. 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?

    0 讨论(0)
  • 2020-12-20 12:32

    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.

    0 讨论(0)
提交回复
热议问题