下面是我的应用程序的简化设置。它有一个 Foobar 类,它调用一个 facade 方法来获取数据。然后,外观调用 Web 服务以实际获取数据,然后对数据进行一些操作,然后将其返回给 Foobar。
现在因为 Web 服务可能需要很长时间才能运行,所以对外观的方法调用需要是异步的。因此,外观的方法没有返回值,而是该方法使用回调对象。查看示例并继续阅读下文。
public class Foobar {
private List<DTO> dtos;
@Autowired
private Facade facade;
public void refresh() {
facade.refreshFoobar(new CallBack() {
public void dataFetched(List<DTO> dtos) {
setDtos(dtos);
}
});
}
public void setDtos(List<DTO> dtos) {
this.dtos = dtos;
}
}
public class Facade {
...
public void refreshFoorbar(CallBack cb) {
// Fetch data from a web service
List<DTO> dtos = webService.getData();
// Manipulate DTOs
....
// call on the callback method
cb.dataFecthed(dtos);
}
}
我有两种方法可以使 facade 的方法异步,通过手动创建线程或使用 springs @Async 注释。
public class Facade {
public void refreshFoorbar(CallBack cb) {
new Thread() {
@Override
public void run() {
....
}
}.start();
}
}
// ... OR ...
public class Facade {
@Async
public void refreshFoorbar(CallBack cb) {
....
}
}
我的问题是我现在需要为这个方法调用链编写一个集成测试。我想我需要在运行集成测试时强制异步外观调用同步,否则我不确定何时可以执行适当的断言。使方法调用同步的唯一想法是使用手动处理的线程并使线程有条件(因此,出于测试目的,我有一个 if 子句来确定外观方法是否应在单独的线程中运行)。
但是,我觉得可能有更好的解决方案来解决我的问题,无论是强制方法同步的更好方法(例如使用 spring),还是通过某种方式测试多线程。
这是我需要你的建议的地方,你会如何解决我的问题?请注意,我将 junit 用于单元测试和集成测试。
最佳答案
简单的解决方案是像这样返回一个 Future 对象,
@Async
public Future<String> refreshFoorbar(CallBack cb) {
yourHeavyLifting(); //asynchronous call
return new AsyncResult<String>("yourJobNameMaybe");
}
在您的测试中,获取 future 的引用并调用 get()方法。
future.get(); // if its not already complete, waits for it to complete
assertTrue(yourTestCondition)
这blog post显示示例。
关于java - 测试异步方法调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7594354/