JUnit ErrorCollector @Rule with Example

โšก Smart Summary

JUnit ErrorCollector is a rule that lets a test keep running after a failure, gathering every error object and reporting them together once the test method finishes instead of stopping at the first problem.

  • ๐Ÿ”˜ Purpose: Continue a test after an assertion, network or GUI check fails, then report every collected error at once.
  • โ˜‘๏ธ Declaration: @Rule on a public non-static ErrorCollector field tells JUnit to attach the rule to each test.
  • โœ… Collecting: addError(Throwable) stores any Error or Exception, because Throwable is the parent of both.
  • ๐Ÿงช Checking: checkThat() evaluates a matcher and records a mismatch without aborting the remaining statements.
  • ๐Ÿ› ๏ธ Reporting: The failure trace lists every collected throwable with its own line number in the JUnit view.
  • ๐Ÿ“Œ JUnit 5: Rules are gone from Jupiter, so assertAll() or AssertJ SoftAssertions play the same role.

JUnit ErrorCollector rule collecting multiple errors in one test run

In a normal scenario, whenever you identify any error during test execution, you would stop the test, fix the error and re-run the test.

But JUnit has a slightly different approach. With the JUnit error collector, you can still continue with the test execution even after an issue is found or the test fails. The error collector collects all error objects and reports them only once, after the test execution is over.

Why use Error Collector?

While writing a test script, you want to execute all the tests even if any line of code fails due to network failure, assertion failure, or any other reason. In that situation, you can still continue executing the test script using a special feature provided by JUnit known as “error collector.”

For this, JUnit uses the @Rule annotation, which is used to create an object of error collector. Once the object for error collector is created, you can easily add all the errors into the object using the method addError (Throwable error). As you know, Throwable is the super class of the Exception and Error classes in Java. When you add errors in this way, these errors will be logged in the JUnit test result.

The benefit of adding all errors in an Error Collector is that you can verify all the errors at once. Also, if the script fails in the middle, execution still carries on to the end of the test method.

Note: In the case of using a simple assert or a try/catch block, using the error collector method will not be possible.

Sample code

To understand more on Error Collector, see the code example below, which demonstrates how to create an Error Collector object and add all the errors to that object to track the issue:

package guru99.junit;		

import org.junit.Rule;		
import org.junit.Test;		
import org.junit.rules.ErrorCollector;		

public class ErrorCollectorExample {				
    @Rule		
    public ErrorCollector collector = new ErrorCollector();							

    @Test		
    public void example() {					
    collector.addError(new Throwable("There is an error in first line"));							
    collector.addError(new Throwable("There is an error in second line"));							
    collector.checkThat(getResults(),			
                not(containsString("here is an error")));			
    // all lines of code will execute and at the end a combined failure will		
    be logged in.		
    }		
}	

Note: this is an illustrative extract, not a compilable file. Its trailing comment wraps onto a second line without a leading //, and getResults() plus the Hamcrest matchers are not shown. The complete runnable version follows under Example using ErrorCollector.

What is @Rule in JUnit?

JUnit provides a special kind of handling of tests, Test Case or test suite by using the @Rule annotation. Using @Rule, you can easily add or redefine the behaviour of the test.

There are several built-in rules provided by the JUnit API that a tester can use, and you can also write your own rule. A rule field must be public, non-static and of a type implementing TestRule.

See the line of code below, which shows how to use the @Rule annotation along with the Error Collector:

@Rule				
public ErrorCollector collector= new ErrorCollector();

JUnit 5 note: Jupiter replaced rules with the Extension API, so @Rule and ErrorCollector do not exist in org.junit.jupiter. The nearest equivalents are Assertions.assertAll() and AssertJ SoftAssertions. The JUnit 4 code shown here still runs through the vintage engine. See the JUnit annotations tutorial for the full mapping.

Example using ErrorCollector

To understand the error collector, let us create a class and a rule to collect all the errors. You will add all the errors using addError(throwable) here.

See the code below, which simply creates a rule that is nothing but an “Error Collector object.” It is further used to add all the errors in order to report the issue at the end:

ErrorCollectorExample.java

package guru99.junit;		

import org.junit.Assert;		
import org.junit.Rule;		
import org.junit.Test;		
import org.junit.rules.ErrorCollector;		

public class ErrorCollectorExample {				
    @Rule		
    public ErrorCollector collector = new ErrorCollector();							

    @Test		
    public void example() {					
    collector.addError(new Throwable("There is an error in first line"));							
    collector.addError(new Throwable("There is an error in second line"));							

        System.out.println("Hello");					
        try {			
            Assert.assertTrue("A " == "B");					
        } catch (Throwable t) {					
            collector.addError(t);					
        }		
        System.out.println("World!!!!");					
    }		
}		

TestRunner.java

Let us add the above test class to a test runner and execute it to collect all the errors. See the code below:

package guru99.junit;		

import org.junit.runner.JUnitCore;		
import org.junit.runner.Result;		
import org.junit.runner.notification.Failure;		

public class TestRunner {				
			public static void main(String[] args) {									
      Result result = JUnitCore.runClasses(ErrorCollectorExample.class);					
			for (Failure failure : result.getFailures()) {							
         System.out.println(failure.toString());					
      }		
      System.out.println("Result=="+result.wasSuccessful());							
   }		
}      

Output:

See the failure trace, which traces all the errors in one place. The JUnit view counts one run but reports two errors and one failure, each with its own line number:

Eclipse JUnit failure trace listing two Throwable errors and one AssertionError collected in a single run

Benefits of JUnit ErrorCollector

You can use a JUnit assertion for functional or GUI validation, for example:

  1. assertEquals(String message, Object expected, Object actual), which compares that two objects are equal.
  2. Similarly, assertTrue(Boolean condition) asserts that a condition is true.

Using assertions, validation testing becomes easy. But one major issue is that test execution will stop even if a single assertion fails.

Test continuity and recovery handling is crucial to test automation success, and it matters most in long Selenium flows where restarting a browser after each failed check is expensive. Error Collector is the best way to handle such scenarios.

FAQs

addError(Throwable) records an error you have already caught or created. checkThat(value, matcher) evaluates a Hamcrest matcher and records a mismatch automatically, so it reads like an assertion while still allowing the remaining statements to run.

Yes. The method runs to completion, then JUnit marks it failed and prints every collected throwable in the failure trace. The example screenshot reports two errors and one failure from a single test method.

JUnit scans the test class for public instance fields annotated with @Rule and applies each one around every test method. A private or static field is ignored, and JUnit raises an initialisation error instead of running the test.

No. Jupiter dropped the rule mechanism, so org.junit.rules.ErrorCollector exists only in JUnit 4. Use Assertions.assertAll() for grouped assertions, or add AssertJ SoftAssertions when richer matchers are needed.

Yes, and it is a common pattern. A page with several fields can be validated in one pass, collecting every mismatch instead of aborting on the first one, which avoids restarting the browser session for each defect found.

Both defer reporting, but SoftAssert requires an explicit assertAll() call at the end of the test, while ErrorCollector reports automatically when the method returns. Forgetting assertAll() in TestNG silently hides failures.

AI assistants group a long failure trace by root cause, so twenty collected throwables reduce to a handful of distinct defects. They also suggest which checks belong together in one collected run rather than in separate tests.

GitHub Copilot writes the @Rule field readily, but it often mixes it into a Jupiter test class where rules do not exist. Confirm the imports are org.junit before running the suite.

Summarize this post with: