如何为run()中具有无限循环的Runnable java类编写UT



我有一个java类如下。它的任务是监视一个文件,如果该文件的大小在一定的时间间隔内没有变化,它将发出警报。

我想为它写两个ut。

1。模拟文件大小保持不变。

2。模拟文件大小保持变化一段时间。之后文件大小将改变。

当条件满足或不满足时,UT将验证是否真的调用了alerter.alert()或alerter.无害()。我模拟Alerter并将其传递给Task的构造函数。但是如何控制run()的时间呢?我知道多线程的时间无法精确控制。我只是想知道,对于这类课程,最好的实践是什么。如果可能的话,请写一个测试样本。

您可以将"some condition"理解为检查指定文件的大小是否每隔一段时间发生变化。如果不改变,某些条件将为真。

class Task implements Runnable{
    Alerter alerter;
    boolean stop=false;
    public Task(Alerter alerter){
        this.alerter=alerter;
    }
    public void run() {
        while (!stop){
            if (some condition){
                alerter.alert();
            } else{
                alerter.harmless();
            } 
            Thread.sleep(5000);
        }
    }
    public synchronized void stop(){
        stop=true;
    }
}

我正在考虑写像下面这样的东西。但我认为它还不够好。

@Test
public void testRunWithFeed() {
    Alerter mockAlerter=mock(Alerter.class);
    Task task=new Task(mockAlerter);
    Thread thread =new Thread(task);
    thread.start();
    try {
        Thread.sleep(1000); // give Task.run() a change to run
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    task.stop();
    try {
        thread.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    verify(mockAlerter,atLeastOnce()).alert();
    verify(mockAlerter,never()).harmless();
}
@Test
public void testRunNoFeed() {
    Alerter mockAlerter=mock(Alerter.class);
    Task task=new Task(mockAlerter);
    Thread thread =new Thread(task);
    thread.start();
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    changeFileSize();
    try {
        Thread.sleep(6000); //because every 5000ms file size will be checked once in run()
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    task.stop();
    try {
        thread.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    verify(mockAlerter,atLeastOnce()).alert();
    verify(mockAlerter,atLeastOnce()).harmless();
}

我认为您不应该调用sleep(),显然也不应该在测试中调用stop。如果您的任务正在运行并且预计将终止,调用join()就足够了:主线程将等待,直到工作线程完成。然后您将验证结果。

还有另一个提示。你应该防止考试卡住。JUnit和TestNG都有定义测试超时的注释。如果超时,测试将被框架终止并自动失败。

例如,对于JUnit,它是属性timout: @Test(timeout=3000)表示3秒。

最新更新