2015-08-22 11 views
7

Vorrei poter utilizzare le regole JUnit come TemporaryFolder o altri TestRule s che abbiamo già sviluppato internamente. Qual è il miglior metodo per farlo? Sono a conoscenza di JUnitSuite ma non sembra raccogliere l'annotazione @Rule. Mi piacerebbe comunque utilizzare una diversa suite ScalaTest.Utilizzo di JUnit @Rule con ScalaTest (ad esempio TemporaryFolder)

Quindi le mie domande sono:

  • sono regole JUnit supportato da un completo ScalaTest?
  • In caso contrario, c'è una libreria là fuori che renderebbe possibile l'uso di Junit TestRule?
  • In caso negativo, come utilizzare JUnit TestRule s nei test Scala?
  • Oppure esiste un approccio più specifico di Scala per la descrizione di ciò che è TemporaryFolder o, ad esempio, di Stefan Birkner System Rules?

Ecco quello che ho provato con 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 
    } 
} 

risposta

8

È possibile risolvere il problema creando un campo membro di tipo TemporaryFolder e restituendo questo valore di campo tramite la funzione @Rule.

class MyTest extends JUnitSuite { 

    val _temporaryFolder = new TemporaryFolder 

    @Rule 
    def temporaryFolder = _temporaryFolder 

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

Ah, grazie, che funziona :). Creazione mancata di più istanze 'TemporaryFolder'. Alla fine, abbiamo optato per la soluzione mixable impilabile in modo che non venisse bloccato con JUnitSuite. Comunque, è bello sapere che '@ Rule' può essere supportato in modo più scalare. – Mifeet

+0

Felice di poter aiutare :-) –

8

Ecco quello che mi è venuta in base a ScalaTest di documentation on fixtures. Tuttavia, mi piacerebbe sapere se c'è una soluzione migliore.

  1. metodo di prestito-dispositivo

    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) 
        } 
        } 
    } 
    
    • Pro: consente di applicare la regola solo per le prove dove è necessario
    • Contro: utilizzo non molto elegante; goffa quando sono necessarie più TestRules
  2. Uso mixins impilabili con withFixture(test: NoArgTest) esclusione

    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) 
        } 
    } 
    
    • Pro: molto semplice utilizzo, convenientemente permette miscelazione più regole in
    • Svantaggi: richiede avente un mixin per ogni regola; le regole devono essere invocate anche per i test che non ne hanno bisogno; la regola non può essere utilizzata per es. in BeforeAfterEach#beforeEach()
  3. Override 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) 
        } 
    } 
    
    • Contro: consente una sola TestRule, facendo in generico per lavorare con qualsiasi regola invece di TestRule richiederebbe uno sforzo supplementare

Quale preferisci?

1

Questo ha funzionato per me. Basato su answer. Così annotazione verrà applicato al al metodo (sintetico) getter

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

class MyTest extends JUnitSuite { 

    @(Rule @getter) 
    val tempFolder = new TemporaryFolder 

} 
Problemi correlati