I'm looking for a way to test my Scala code with multiple inputs. Comming from Java/JUnit, I immediately thought of @RunWith(Theories.class).
Where I'm stuck is the usage of @DataPoints and the absence of static members/methods in Scala. So is there a way to write the following code in Scala?
@RunWith(classOf[Theories])
class ScalaTheory {
@DataPoints
val numbers = Array(1, 2, 3)
@Theory
def shouldMultiplyByTwo(number : Int) = {
// Given
val testObject = ObjectUnderTest
// When
val result = testObject.run(number)
// Then
assertTrue(result == number * 2)
}
}
I'm neither fixed on JUnit nor Theories so if there is something Scala-specific for this use case, I'm happy to use that.
To make this work, you have to do two things: use a method[see edit below], not a value, and secondly, define your @DataPoints in a companion object. The following should work:
object ScalaTheory {
@DataPoints
def numbers() = Array(1, 2, 3) // note def not val
}
@RunWith(classOf[Theories])
class ScalaTheory {
@Theory
def shouldMultiplyByTwo(number : Int) = {
// Given
val testObject = ObjectUnderTest
// When
val result = testObject.run(number)
// Then
assertTrue(result == number * 2)
}
}
When you define methods or fields in a companion object in Scala, you get a static forwarder in the class. Decompiling using JAD:
@Theories
public static final int[] numbers()
{
return ScalaTheory$.MODULE$.numbers();
}
So this takes care of the static problem. However, when we use a val numbers = ..., the annotation isn't carried over to the field, but it is for methods. So using def works.
As the others have said, if you're developing from scratch, it may be worth starting in a Scala framework like scalatest. The tool integration with scalatest is improving (i.e maven, Eclipse, Intellij), but it's not the level of JUnit, so evaluate it for your project before you start.
EDIT: In fact, after this discussion on scala-user, you can use val, but you need to tell the scala compiler to apply the DataPoints annotation to the static forwarder:
object ScalaTheory {
@(DataPoints @scala.annotation.target.getter)
val numbers = Array(1, 2, 3)
}
The getter annotation says that the @DataPoints annotation should be applied to the accessor method for the numbers field, that is the numbers() method which is created by the compiler. See package target.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With