'Arquillian and TimerService

So I have an EJB that has a @Schedule annotated method, and I want to test it using arquillian, what I can easily do invoking the method directly, but because the deployment is being run on wildfly the timer service is started and the scheduled method will run more than expected causing test failures.

How can I disable the timer service when using arquillian? Or is there other way to properly test the timers



Solution 1:[1]

Johannes Hahn's answer will certainly do what you want, but if you wished to control code execution in a more general purpose way you could use a system property and test its value when timeout is called. Also note that System properties can be also created/set/modified/removed at runtime in the JBoss Administration Console.

In the example below the timer will completely execute doThings() when the container is started with -DstartTestTimer=true but will exit prematurely if it is not set, or if it is set to false.

@Singleton
@Startup
public class TestTimer {
    @Resource
    private TimerService timerService;

    @PostConstruct
    public void initialize() {
        ScheduleExpression expression = new ScheduleExpression();
        expression.hour("*");
        timerService.createCalendarTimer(expression, new TimerConfig("My Timer", false));
    }

    @Timeout
    public void doThings() {
        if (!Boolean.getBoolean("startTestTimer")) {
            return;
        }
        // code to be executed in Timer here:
    }
}

Solution 2:[2]

It is possible. You can write an interceptor with an @AroundTimeout method. That intercepts all @Schedule and @Timeout methods. In the interceptor you simply never proceed to the method so that all calls the TimerService makes are blocked.

@Interceptor
@TimeoutInterceptorBinding
public class TimerInterceptor {

    @AroundTimeout
    public Object disallowTimeoutMethods(InvocationContext context){
        // simply never call context.proceed() => all @Schedule and @Timeout methods are blocked

        // return null, because @Schedule and @Timeout methods all have return type void
        return null;
    }
}

This interceptor is then of course only active in the test environment and then you can happily call the timed methods explicitly if and when you want them in your test.

Solution 3:[3]

You definitely shouldn't disable a timer service (and any other EJB container services).

IMHO the best way to go would be to abandon a direct call of the @Schedule method. It would be the least intrusive method.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Dennis Ryan
Solution 2 Johannes Hahn
Solution 3 G. Demecki