如何触发@Timeout注解?

How to trigger @Timeout annotation?

我正在创建 EJB TimerService 模拟。有没有办法手动触发对带有@Timeout 注释的方法的调用?

您可以创建具有首选持续时间的新计时器。当您需要调用超时时,请调用下面带有持续时间的代码段。然后框架应该在给定的持续时间内调用超时方法。

上下文。getTimerService().createTimer(持续时间,"Hello World!");

完整代码

import javax.annotation.Resource;
import javax.ejb.SessionContext;
import javax.ejb.Timer;
import javax.ejb.Stateless;
import javax.ejb.Timeout;

@Stateless
public class TimerSessionBean implements TimerSessionBeanRemote {

    @Resource
    private SessionContext context;

    public void createTimer(long duration) {
    context.getTimerService().createTimer(duration, "Hello World!");
    }

    @Timeout
    public void timeOutHandler(Timer timer){
    System.out.println("timeoutHandler : " + timer.getInfo());        
    timer.cancel();
    }
}

现在让我们考虑一下

The method is not public.

如果您只想测试用@Timeout注释的方法中包含的逻辑,解决方案很少。 我会推荐最后一个,因为它也会改进整体设计(参见 this answer)。

  1. 使该方法受保护或包私有。这是使该逻辑可测试的最简单方法。
  2. 使用反射或PowerMock调用私有方法。

这是一个简单的例子,假设我们要调用 instance.timeOutHandlerMethod with Timer 实例 timer.

Whitebox.invokeMethod(instance, "timeOutHandlerMethod", timer);

有关详细信息,请参阅 doc page

  1. 提取逻辑以分离 class 并对其进行测试。

这里我们提取逻辑从this.timeOutHandlerDelegate.execute:

@Timeout
private void timeOutHandler(Timer timer) {
    // some complicated logic
    timer.cancel();
}

对此:

private Delegate delegate;

@Timeout
private void timeOutHandler(Timer timer) {
    delegate.execute(timer);
}

Delegate 声明为:

class Delegate {

    public void execute(Timer timer) {
        // some complicated logic
        timer.cancel();
    }
}

现在我们可以为 Delegate class.

编写测试