junit测试只有在我逐个运行时才能通过可能螺纹不正确

kuhbmx9i  于 2021-06-29  发布在  Java
关注(0)|答案(1)|浏览(238)

upd:有标记的答案解决了这个问题,请参阅小补丁的注解。
首先请原谅我的残暴行为。这个问题让我发疯,为了确定问题的根源,我尝试了很多东西,但都失败了。
我有一个springbootweb应用程序,它有fmonitor服务。它在应用程序运行时工作,当某个文件夹中出现扩展名为“.done”的文件时,它会通知我。当我运行这个应用程序的时候,它运行得非常完美(至少看起来是这样)。
我决定练习考试,并抛出了三个简单的。当我一次一个地运行它们时,它们工作得很成功。然而,当我运行整个类的测试时,只有前一个通过,其他两个失败。
我的测试检查系统,并将其与所需的输出进行比较。对我来说最奇怪的是。事情就是这样。
第一次测试通过时,fmonitor的输出与assertequals中的完全相同。找到test1找到test2找到test3
第二次测试失败。由于某种原因,输出奇怪地翻了一番:foundtest1foundtest1foundtest3foundtest3
第三个失败了。现在输出是三倍:found testfound test
我的猜测是我对线程做了一些完全错误的事情,所以fm.monitor()以某种方式捕获了所有事件之类的东西。我很困惑。我在这里尝试了很多关于如何实现线程的方法,我不太擅长,但它仍然可以工作。我还认为@async annotation for monitor()可能会弄乱一些东西,但删除它并没有改变任何东西。请救命。
束流试验

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.io.*;
import java.util.concurrent.Executor;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = FMonitor.class)
public class BunchOfTests {
    private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
    private Executor executor;

    @Autowired
    FMonitor fm;

    @Test
    public void test1() throws InterruptedException, IOException {
        Runnable task = () -> {
            System.setOut(new PrintStream(outContent));
            fm.monitor();
            System.setOut(System.out);
        };
        executor = (runnable) -> new Thread(runnable).start();
        executor.executeTask(task);
        Thread.sleep(3000);
        File file1 = new File("C:\\dir\\test1.done");
        File file2 = new File("C:\\dir\\test2.done");
        File file3 = new File("C:\\dir\\test3.done");
        file1.createNewFile();
        file2.createNewFile();
        file3.createNewFile();
        Thread.sleep(3000);
        file1.delete();
        file2.delete();
        file3.delete();
        Assert.assertEquals("Found test1\r\n" + "Found test2\r\n" + "Found test3\r\n", outContent);
    }

    @Test
    public void test2() throws InterruptedException, IOException {
        Runnable task = () -> {
            System.setOut(new PrintStream(outContent));
            fm.monitor();
            System.setOut(System.out);
        };
        executor = (runnable) -> new Thread(runnable).start();
        executor.executeTask(task);
        Thread.sleep(3000);
        File file1 = new File("C:\\dir\\test1.done");
        File file2 = new File("C:\\dir\\test2.txt");
        File file3 = new File("C:\\dir\\test3.done");
        file1.createNewFile();
        file2.createNewFile();
        file3.createNewFile();
        Thread.sleep(3000);
        file1.delete();
        file2.delete();
        file3.delete();
        Assert.assertEquals("Found test1\r\n" + "Found test3\r\n", outContent);
    }

    @Test
    public void test3() throws InterruptedException, IOException {
        Runnable task = () -> {
            System.setOut(new PrintStream(outContent));
            fm.monitor();
            System.setOut(System.out);
        };
        executor = (runnable) -> new Thread(runnable).start();
        executor.executeTask(task);
        Thread.sleep(3000);
        File file = new File("C:\\dir\\test.done");
        file.createNewFile();
        Thread.sleep(3000);
        file.delete();
        Assert.assertEquals("Found test\r\n", outContent);
    }
}

F监视器

import org.springframework.stereotype.Service;
import org.srpingframework.scheduling.annotation.Async;

import java.io.IOException;
import java.nio.file.*;

@Service
public class FMonitor {

    @Async("fMonitor")
    public void monitor() {
        Path path = Paths.get("C:\\dir");
        try {
            WatchService watchService = FileSystems.getDefault.newWatchService();
            path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE);
            WatchKey key;
            while ((key = watchService.take()) != null) {
                for (WatchEvent<?> event: key.pollEvents()) {
                    String filename = event.context().toString();
                    if (filename.endsWith(".done")) {
                        processFile(filename.substring(0, filename.lastIndexOf('.')));
                    }
                }
                key.reset();
            }
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void processFile(String filename) {
        System.out.println("Found " + filename);
    }
}

A配置

import org.srpingframework.context.annotation.Bean;
import org.srpingframework.context.annotation.Configuration;
import org.srpingframework.scheduling.annotation.EnableAsync;

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

@Configuration
@EnableAsync
public class AConfiguration {
    @Bean(name = "fMonitor")
    public Executor asyncExecutor() { return Executors.newSingleThreadExecutor(); }
}
ovfsdjhp

ovfsdjhp1#

首先,你应该干净利落地停止 WatchService 当你完成的时候。实现一个这样做的方法,并用 @PreDestroy .

@Service
public class FMonitor {

    private final WatchService watchService = FileSystems.getDefault.newWatchService();

    @Async("fMonitor")
    public void monitor() {
        Path path = Paths.get("C:\\dir");
        try {
            path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE);
            WatchKey key;
            while ((key = watchService.take()) != null) {
                for (WatchEvent<?> event: key.pollEvents()) {
                    String filename = event.context().toString();
                    if (filename.endsWith(".done")) {
                        processFile(filename.substring(0, filename.lastIndexOf('.')));
                    }
                }
                key.reset();
            }
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void processFile(String filename) {
        System.out.println("Found " + filename);
    }

    @PreDestroy
    public void shutdown() {
      try {
        watchService.close();
      } catch (IOException ex) {}
    }
}

下一个不要用 @SpringBootTest 它只会增加测试的复杂性和缓慢性。相反,只需自己示例化它,并使用适当的执行器来启动 monitor 方法。

public class BunchOfTests {

    @Rule
    public OutputCaptureRule output = new OutputCaptureRule();

    private ExecutorService executor = Executors.newSingleThreadExecutor();

    private final FMonitor fm = new FMonitor();

    @After
    public void cleanUp() throws Exception {
      fm.shutdown();
      executor.shutdown();
      while (!executor.awaitTermination(100, TimeUnit.MICROSECONDS));
    }

    @Test
    public void test1() throws InterruptedException, IOException {
        executor.submit(() -> fm.monitor());

        Thread.sleep(3000);
        File file1 = new File("C:\\dir\\test1.done");
        File file2 = new File("C:\\dir\\test2.done");
        File file3 = new File("C:\\dir\\test3.done");
        file1.createNewFile();
        file2.createNewFile();
        file3.createNewFile();

        Thread.sleep(3000);
        file1.delete();
        file2.delete();
        file3.delete();
        Assert.assertEquals("Found test1\r\n" + "Found test2\r\n" + "Found test3\r\n", output.toString());
    }

    @Test
    public void test2() throws InterruptedException, IOException {
        executor.submit(() -> fm.monitor());

        Thread.sleep(3000);
        File file1 = new File("C:\\dir\\test1.done");
        File file2 = new File("C:\\dir\\test2.txt");
        File file3 = new File("C:\\dir\\test3.done");
        file1.createNewFile();
        file2.createNewFile();
        file3.createNewFile();

        Thread.sleep(3000);
        file1.delete();
        file2.delete();
        file3.delete();
        Assert.assertEquals("Found test1\r\n" + "Found test3\r\n", output.toString());
    }

    @Test
    public void test3() throws InterruptedException, IOException {
        executor.submit(() -> fm.monitor());

        Thread.sleep(3000);

        File file = new File("C:\\dir\\test.done");
        file.createNewFile();

        Thread.sleep(3000);
        file.delete();
        Assert.assertEquals("Found test\r\n", output.toString());
    }
}

像这样的事情或多或少应该做你想做的。

相关问题