2

Checkinging many XML strings, I use the ErrorCollector construction frequently. But still I do not understand how it works.

When I am declaring an ErrorCollector, I have to assign it at once:

@Rule
public ErrorCollector collector= new ErrorCollector();

If I want to refresh the collector before every test, I am putting an assignment

collector= new ErrorCollector();

in the @Before method. But thus the first assignment at the declaration is excessive. But I can't remove it.

What is the sense of this must-to-be-assignment? And how it works? I thought, that @Rule is about the declaration only?

@Matthew Farwell at What is the logic of @Rule(JUnit) declaration and assignment in a Groovy class says "In Java, the JUnit runner checks that the @Rule annotation is applied to a public non-static field or public non-static method which returns either a TestRule or MethodRule." But what is checked here is not the declaration, but the assignment and it is something that happens afterwards, after both building and test construction ?

Community
  • 1
  • 1
Gangnus
  • 24,044
  • 16
  • 90
  • 149
  • What is `test-construction` and why does it apply to this question, while `unit-testing` does not? – Charles Apr 16 '13 at 16:20

1 Answers1

4

As with most / all @Rules in JUnit, they are refreshed or cleared before each test automatically. So you just declare it as a @Rule as you have listed above. You DO NOT need to do anything to it in your @Before method. We way to think of it is that JUnit will invoke the ErrorCollector before and after each test. Before each test the ErrorCollector can initialize itself (clearing any previously stored errors). After each test, if an error has been collected it reports the error(s).

Here is the source for ErrorCollector

From Comment:

It must be assigned because JUnit must have an instance of the rule to work with. Otherwise the object would be null. Remember that the JUnit code is using reflection to get the instance of the Object with the @Rule annotation and using instanceof to determine if it is a TestRule or MethodRule. I believe the @Before method is called within the Statement and therefore after the Rule is invoked

FROM MatthewFarwell:

When you run a JUnit test, for example, FooTest, then the runner will create an instance of FooTest for each test method. So if you're using public ErrorCollector collector= new ErrorCollector(); as above, then this gets naturally re-instantiated once per test method.

Conclusing: Make sure that you don't save state between your tests! Of course you shouldn't have done that anyway since order is not guaranteed.

Thanks Matt!

John B
  • 32,493
  • 6
  • 77
  • 98
  • "Before each test the ErrorCollector can initialize itself" 1. So, can or shall? 2. Thank you, and have a +1, but I would like to understand the behaviour of that @Rule annotation. – Gangnus Apr 12 '13 at 10:59
  • 1. You shouldn't care. The point is that you don't have to do anything other than declare it as a `@Rule`. 2. The `@Rule` annotation is used by JUnit to identify `TestRule` instances that should be used to wrap each test method. JUnit wraps the execution of each test in a `Statement` and then provides the `Statement` to each found `Rule` in order for the `Rule` to wrap the statement with its own custom logic. – John B Apr 12 '13 at 12:04
  • It seems, that I have understood, thank you. But that doesn't explain why have I to use assignment in the declaration statement. I can read source code, it is not a problem. But WHAT source code have I to read - that is the question. – Gangnus Apr 12 '13 at 12:29
  • It must be assigned because JUnit must have an instance of the rule to work with. Otherwise the object would be null. Remember that the JUnit code is using reflection to get the instance of the Object with the @Rule annotation and using `instanceof` to determine if it is a `TestRule` or `MethodRule`. I believe the @Before method is called within the Statement and therefore after the Rule is invoked. – John B Apr 12 '13 at 12:44
  • +1 However, more correctly, JUnit creates an instance of the enclosing class for each test method, so no 'cleaning' is necessary. – Matthew Farwell Apr 12 '13 at 13:28
  • @JohnB So, the assignment happens during the construction of the test? Could you put this explanation into the answer from the comment, please? – Gangnus Apr 12 '13 at 13:42
  • @Matthew would you please clarify? I didn't see the "cleanup" logic in the ErrorCollector so wondered how this was done. I see that each test's statement is wrapped in a new statement for error collection but the wrapping statement is still referring to "this" error handler so how are multiple error handlers being instantiated? – John B Apr 12 '13 at 15:52
  • 2
    @JohnB When you run a JUnit test, for example, FooTest, then the runner will create an instance of FooTest for each test method. So if you're using public ErrorCollector collector= new ErrorCollector(); as above, then this gets naturally re-instantiated once per test method. – Matthew Farwell Apr 12 '13 at 16:00
  • @MatthewFarwell WOW! I didn't know that but it explains a lot. Thanks. I was running a test and noticing that for each test I had a different ErrorCollector instance and was wondering how that happened. – John B Apr 12 '13 at 16:03