Java:如何单元测试摇摆工人



搜索了一段时间后,我仍然无法找到自己喜欢的答案。

我有一个Swingworker执行"长"任务,与DB交谈并返回结果。我想为此编写一个单元测试,并为我的DB一个模拟对象。

我在此处基于这篇很棒的帖子实施了我的摇摆工作者:

如何使此摇摆工具可测试

但是,它实际上没有设备测试逻辑。而且我还没有看到任何关于最佳实践的精彩文章,这使我相信我缺少一些基本的东西。是否简单地检查完成的循环检查吗?还是我应该利用更复杂的东西?还是最佳实践仅仅是为了构建对正在测试的逻辑的同步访问点?

- 编辑:我添加了Swingworker代码,以查看如何实现它。所以我的问题是:如何为此课程编写有效单元测试?

public class MovieListLoaderWorker extends SwingWorker<ArrayList<String>, ArrayList<String>> {
//private Model model;
private MovieListDB db;
private Response target;
private boolean keepAlive = false;
public MovieListLoaderWorker(MovieListDB db, Response target) {
    this.db = db;
    this.target = target;
}
public MovieListLoaderWorker( boolean keepAlive, MovieListDB db, Response target) {
    this.db = db;
    this.target = target;
    this.keepAlive = keepAlive;
}
/**
 * @return List of movies (synchronous)
 */
public ArrayList<String> getMovieList() {
    ArrayList<String> movieNames = new ArrayList<String>(db.getMovieSet(true));     
    Collections.sort(movieNames);
    return movieNames;      
}
protected ArrayList<String> doInBackground() throws Exception {
    target.started();
    // if we want to keep the Thread alive, we spin and publish movie lists
    while (keepAlive) {
        publish(getMovieList());
        Thread.sleep(Config.MOVIE_LIST_REFRESH_RATE_MILLIS);
    }
    // only run once, and simply return the Movie list.
    return getMovieList();
}
@Override
protected void process(List<ArrayList<String>> list) {
    ArrayList<String> s = list.get(list.size() - 1);
    target.statusUpdate(s);
    super.process(list);        
}
@Override
protected void done() {
    try {
        ArrayList<String> movieNames = get();
        if (movieNames == null) {
            target.failure(new BackgroundException(new Exception("Unable to load movie names.")));
        }
        else {
            target.success(movieNames);
        }
    }
    catch (InterruptedException ex) {
        target.failure(new BackgroundException(ex));
    }
    catch (ExecutionException ex) {
        target.failure(new BackgroundException(ex));
    }
}
public interface Response {     
    void started();
    void statusUpdate(ArrayList<String> list);
    void success(ArrayList<String> movieList);
    void failure(BackgroundException ex);
}
public class BackgroundException extends Exception {
    public BackgroundException(Throwable cause) {
        super(cause);
    }
}
}

您必须在此处清楚责任。

一个部分是必须与该数据库交谈的实际"服务",并且您想通过Swingworker运行。

我将实现该 dbservice 完全独立于线程上下文。 dbservice 类也具有 no 与Swingworker的关系。这是一个提供特定服务的"独立"类,可以完全测试单位,而不必担心Swingworker或Threads。

然后创建自己的小摇摆工人,该工厂使用该 dbservice 并使用该对象进行工作。

现在,您可以将 dbservice 的模拟实例纳入您的Swingworker;您可以使用单元测试来确保"接线"正确。

换句话说:不要将完整的功能推向摇摆工。相反,这里有单独的担忧;因为这也导致"测试需求"的分离。

因此,作为如何进行单元测试的实现,我想出的摇摆工人会感谢任何反馈。而且,如果您像我一样,难以为这个问题找到一个体面的资源,我希望它对您有所帮助。

第一个示例是利用jodah.net的服务员功能。这将迫使通话线等到摇摆工人返回。您可以在匿名响应对象中对摇摆工作者的结果进行任何必要的断言,并直接进行异常测试。

//here's the Waiter import, among others that you'll need
import net.jodah.concurrentunit.Waiter;
@Test
public void testExecute_AsyncExample1() throws Throwable {
    final Waiter waiter = new Waiter();
    MovieListLoaderWorker mlw = new MovieListLoaderWorker(db, new Response() {
        @Override
        public void success(ArrayList<String> movieList) {
            waiter.assertNotNull(movieList);
            waiter.assertTrue(movieList instanceof ArrayList);
            waiter.assertEquals(3, movieList.size());
            waiter.resume();
        }
        @Override
        public void started() {                             
        }
        @Override
        public void failure(BackgroundException ex) {               
        }
        @Override
        public void statusUpdate(ArrayList<String> list) {              
        }
    });
    mlw.execute();
    waiter.await(1, TimeUnit.SECONDS);      
}

第二个示例非常简单,并利用了SwingWorker.get()块直到返回的事实。get()返回时,Swingworker提出的例外将传递给呼叫者。

@Test
public void testExecute_AsyncExample2() throws Throwable {
    MovieListLoaderWorker mlw = new MovieListLoaderWorker(db, response);    
    mlw.execute();
    mlw.get();  //blocking so we can verify
    verify(response).started();
    verify(db).getMovieSet(true);
}

我为自己锻炼的两种模式。对其他意见感兴趣。

相关内容

  • 没有找到相关文章

最新更新