Hello,

I came across this issue (https://github.com/KentBeck/junit/issues/83) recently, and I've created a fork & patch for it, but before I submit the pull request, I wanted to check with the development list to see if I've done the correct thing, and because this is the first contribution I've done for junit.

The problem is this: Scala does not support the creation of public fields. When you define a field with a public access modifier, this gets implemented in the bytecode as a private field with public accessors. Therefore, it is impossible to use @Rule annotations correctly. So, for instance, the following code throws a initializationError ("Field thrown must be public"):

import org.junit._

class ClassTest {
  @Rule val thrown = ExpectedException.none()

  @Test
  def badInt: Unit = {
    thrown.expect(classOf[NumberFormatException])
    Integer.parseInt("one")
  }
}

even though everything looks correct from the point of view of the developer (Scala fields and methods are public by default). One solution would be to allow non-public fields to be used for @Rule annotations, but this was rejected in (https://github.com/KentBeck/junit/issues/31). Another solution to this problem is to allow the @Rule annotation to apply to methods as well. So, in java, you'd have:

public class ExampleTest {
private ExpectedException thrown = ExpectedException.none();
@Rule
public TestRule getThrown() {
return thrown;
}

@Test
public void badInt() {
            thrown.expect(NumberFormatException.class);
            Integer.parseInt("one");
}
}

and Scala:

class ClassTest {
  private val vthrown = ExpectedException.none()
  @Rule def thrown() = vthrown

  @Test
  def badInt: Unit = {
    vthrown.expect(classOf[NumberFormatException])
    Integer.parseInt("one")
  }
}

To keep things consistent, @ClassRule is also applicable to methods.

This is the change that I've made. It is available as a branch on my fork of junit @ github: https://github.com/matthewfarwell/junit/commit/c82458623b1dd5ed65d4f59e6f2b769f1338e13d

The main change is to BlockJUnit4ClassRunner#getTestRules() and ParentRunner#classRules(). After creating the list of TestRule from the @Rule annotated fields, it calls all of the @Rule annotated methods and adds the TestRule objects returned to the list of TestRule. This means that if a field and method are annotated with @Rule, then the field comes first, then the method. However, if multiple fields are defined, then the order is still undefined.

Validation for the @Rule annotated methods is as you would expect, the methods must be public and return a TestType. In the case of @ClassRule, it must also be static.

Could I please have some feedback on this: tell me if it fits in with the current direction of junit development, and if it is an acceptable feature?

I am completely open to any suggestions or criticisms of my code.

Thanks.

Matthew Farwell.