Serenity BDD – Register a custom listener

with 3 Comments

At this moment I am working for a insurance company where I am part of a team developing a test automation solution. For this purpose we use Serenity BDD with JBehave.
During our daily routine we sometimes find the need to enhance the default behaviour of Serenity BDD or fix issues we find etc. In this blog series I will write up some of

things we have done.


During one day I was browsing through some of the code from Serenity. And in particular I looked at the StepEventBus. The following is stated in the Doc Comment with this class;

An event bus for Step-related notifications.
Use this to integrate Thucydides listeners with testing tools.
You create a listener (e.g. an instance of BaseStepListener, or your own), register it using
'registerListener', and then implement the various methods (testStarted(), stepStarted()). Thucydides
will call these events on your listener as they occur.
You can register a new Thucydides listener by implementing the StepListener interface and
placing your class in the classpath. Thucydides will automatically detect the listener and add it to the
registered listeners. It will load custom listeners automatically when a test starts for the first time.


If you would focus on the bold part of this comment, it states that one can create a class which implements the StepListener interface which will automatically be loaded when placed on the classpath.
Further on in the class you can find the following comment on the registerListener method;

Register a listener to receive notification at different points during a test's execution.
If you are writing your own listener, you shouldn't need to call this method - just set up your
listener implementation as a service (see,
place the listener class on the classpath and it will be detected automatically.


As I am not a full-blown Java developer, I did not exactly knew what to do from the start. I had never used a service before and I never thoroughly read the mentioned ServiceLoader documentation until after I searched google for ‘java serviceloader’, ‘how to load a service in java’ etc.

I think anyone can register a service by reading through the documentation by Oracle and following the example that is written there, but in the following part I have written down an example of using this to register a custom listener for Serenity.


  • create a new class which will be the custom listener, eg. MyCustomListener
  • this class must implement StepListener (from the package net.thucidydes.core.steps)
  • and implement all necessary methods and adjust to you own needs


  • in the resources folder of the project you are using create a directory META-INF
  • within the META-INF directory create a new directory services
  • now create a new file in the services directory with the name net.thucydides.core.steps.StepListener
  • open the newly created file and add the class you created earlier with its fully qualified name eg. nl.detesters.MyCustomListener


Now when you start a test Serenity will load your custom listener and as events are called, Serenity will trigger those events on all listeners that are registered including your own custom listener.
you can check if your custom listener is loaded by debugging a test and placing a breakpoint in the getCustomListeners() method in StepEventbus (line: 164)


Added note (on 2017/07/17)
For as far as I can see the priority of StepListeners is as follows when an event triggers;

BaseStepListener  >  other Registered Listeners  >  Custom Listeners


Happy testing! 😀


  • Anji Prassana

    Its not working having the runner cucumberWithSerenity.class. I am not sure whether it works for you with SerenityRunner.class approach. For me, I am using cucumberWithSerenity.class for my Junit tests, but the listener is not called

  • Anji Prassana

    Sorry!! It’s calling. We must use some @step annotated methods in our code.

  • schenkweb

    Hello@anjiprassana:disqus , I’m glad it worked for you. And thanks for you addition. You indeed need to have @Step annotated methods.