javaspringtestingtestnglisteners

How can I get TestNG ITestResult in Spring test listener?


I'm writing tests using Spring and TestNG. An example of a test class:

@SpringBootTest
@TestExecutionListeners(
        mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS,
        listeners = {TestListener.class}
)
public class BaseTest extends AbstractTestNGSpringContextTests
{
}

My TestListener class extends TransactionalTestExecutionListener so I have override methods for beforeTestClass(TestContext testContext), afterTestMethod(TestContext testContext) etc.

My problem is that within afterTestMethod I need to be able to get the TestNG ITestResult or TestResult so I can do different things depending on test success, fail or skip etc. Is there any way I can access ITestResult or TestResult from a spring test listener?


Solution

  • There is no easy direct way of getting access to the ITestResult object of a test method that was executed because Spring doesn't seem to provide access to it.

    You can try doing something like this:

    Here's how a sample implementation could look like:

    public class MyListener extends TransactionalTestExecutionListener {
        @Override
        public void afterTestMethod(TestContext testContext) throws Exception {
          super.afterTestMethod(testContext);
          ITestResult currentTestResult = getCorrespondingResultFor(testContext.getTestMethod());
        }
    
        private ITestResult getCorrespondingResultFor(Method method) {
          ITestContext context = Reporter.getCurrentTestResult().getTestContext();
          Set<ITestResult> allResults = new HashSet<>();
          allResults.addAll(context.getPassedTests().getAllResults());
          allResults.addAll(context.getFailedTests().getAllResults());
          allResults.addAll(context.getSkippedTests().getAllResults());
          return allResults
              .stream()
              .filter(result -> result.getMethod().getConstructorOrMethod().getMethod().equals(method))
              .findAny()
              .orElse(null);
        }
    }