2015-08-22 2 views
7

Я хотел был бы иметь возможность использовать правила JUnit, такие как TemporaryFolder или другие TestRule s, которые мы уже разработали сами. Каков наилучший способ для этого? Я знаю JUnitSuite, но, похоже, он не подхватил аннотацию @Rule. Я бы хотел использовать другой набор ScalaTest.Использование JUnit @Rule с ScalaTest (например, TemporaryFolder)

Так что мои вопросы:

  • Поддерживаются JUnit правила по ScalaTest костюм?
  • Если нет, есть ли библиотека, которая могла бы использовать с помощью Junit TestRule s?
  • Если нет, то как использовать JUnit TestRule s в тестах Scala?
  • Или существует более подходящий подход, основанный на применении Scala для обеспечения того, что TemporaryFolder, или, например, System Rules Стефана Биркнера?

Вот что я пытался с 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 
    } 
} 

ответ

8

Вы можете решить эту проблему, создав поле-член типа TemporaryFolder и вернув это значение по @Rule.

class MyTest extends JUnitSuite { 

    val _temporaryFolder = new TemporaryFolder 

    @Rule 
    def temporaryFolder = _temporaryFolder 

    @Test 
    def test: Unit = { 
    assert(temporaryFolder.newFile() !== null) 
    } 
} 
+0

Ах, спасибо, что работает :). Отсутствует создание нескольких экземпляров 'TemporaryFolder'. В конце концов, мы пошли со сложным решением mixins, чтобы мы не запирались с JUnitSuite. Но в любом случае, хорошо знать, что '@ Rule' может поддерживаться в scalatest. – Mifeet

+0

Рад, что я мог бы помочь :-) –

8

Вот что я придумал на основе ScalaTest-х documentation on fixtures. Тем не менее, я хотел бы знать, есть ли лучшее решение.

  1. метод Loan-светильник

    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) 
        } 
        } 
    } 
    
    • Плюсы: позволяет применить правило только к тестам, где это необходимо
    • Минусы: не очень элегантное использование; неуклюже, когда несколько TestRules требуется
  2. Использования наращиваемых Примеси с 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) 
        } 
    } 
    
    • За: очень простым использованием, удобно позволяет смешивать несколько правил в
    • Cons: требует наличия в Mixin для каждое правило; правила должны быть вызваны даже для тестов, которые им не нужны; правило не может использоваться, например. в BeforeAfterEach#beforeEach()
  3. Переопределение 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) 
        } 
    } 
    
    • Минусы: позволяет только один TestRule, что делает в родовое работать с любым правилом, а не только TestRule потребует дополнительных усилий

Какой вам больше всего нравится?

1

Это сработало для меня. На основании answer. Так аннотации будут применяться к методе (синтетический) газопоглотительного

import org.junit._ 
import scala.annotation.meta.getter 

class MyTest extends JUnitSuite { 

    @(Rule @getter) 
    val tempFolder = new TemporaryFolder 

} 
Смежные вопросы