UPD : 표시된 답변으로 문제가 해결되었습니다. 작은 수정 사항에 대한 설명을 참조하십시오.
우선 도살 된 코드를 용서 해주세요. 이 문제는 나를 미치게 만들고 문제의 원인을 파악하기 위해 많은 것을 시도했지만 실패했습니다.
FMonitor 서비스가있는 Spring Boot 웹 앱이 있습니다. 앱이 실행되는 동안 작동하며 특정 폴더에 ".done"확장자를 가진 파일이 나타나면 알려줍니다. 앱을 실행하면 완벽하게 작동합니다 (적어도 그런 것 같습니다).
나는 시험으로 연습하기로 결정하고 간단한 세 가지를 던졌습니다. 한 번에 하나씩 실행할 때 성공으로 작동합니다. 그러나 전체 테스트 클래스를 실행할 때 처음 하나만 통과하고 다른 두 개는 실패합니다.
내 테스트는 System.out을 확인하고 원하는 출력과 비교합니다. 그리고 여기 저에게 가장 이상한 것이 있습니다. 그게 무슨 일이야.
첫 번째 테스트를 통과하면 FMonitor의 출력이 assertEquals에서와 똑같습니다. test1을 찾았습니다. test2를 찾았습니다. test3 발견
두 번째 테스트가 실패합니다. 출력은 어떤 이유로 이상하게 두 배가됩니다. test1을 찾았습니다. test1을 찾았습니다. test3 발견 test3 발견
그리고 세 번째는 실패합니다. 출력은 이제 3 배입니다. 찾은 테스트 찾은 테스트 찾은 테스트
내 생각 엔 내가 쓰레드로 완전히 잘못된 일을했기 때문에 fm.monitor ()는 어떻게 든 모든 이벤트와 그와 비슷한 것을 잡는다. 나는 매우 혼란 스럽습니다. 여기에서 스레딩을 구현하는 방법에 대해 많은 것을 시도했지만 잘하지 못했지만 여전히 동일하게 작동합니다. 또한 monitor ()에 대한 @Async 주석이 뭔가를 엉망으로 만들 수 있다고 생각했지만 제거해도 아무것도 변경되지 않았습니다. 도와주세요.
BunchOfTests
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);
}
}
FMonitor
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);
}
}
AConfiguration
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(); }
}
- 답변 # 1
관련 자료
- java - 다른 JUnit 테스트 세트에 여러 설정을하는 방법은 무엇입니까?
- java - IntelliJ에서 JUnit 5 테스트를 실행할 때 오류가 발생하지만 명령 행에서는 오류가 발생하지 않습니다
- java - 동일한 WebDriver 객체를 사용하여 여러 JUnit 테스트 실행
- scala - Mill으로 JUnit 테스트를 실행하는 방법
- java - Junit 테스트는 공유 인스턴스로 인해 실패합니다 (생각합니다)
- java - Junit 5 및 스프링 부트 2가있는 Mokito 2에서 테스트를 찾지 못했습니다
- java - JUnit 5 테스트가 실행되지 않고 테스트 실행기에 테스트가 표시되지 않음
- unit testing - soapui-maven-plugin의 junit 보고서의 일부로 성공 테스트를 포함하는 방법
- java - Maven surefire를 사용하여 mpirun으로 Junit 테스트 실행
- java - JUnit 0 테스트를 찾았습니다
- java - busienss 논리 및 DB 연결을위한 Junit 스프링 부트 유닛 테스트
- automation - 잘못된 Chromedriver 버전 사용으로 인해 Vividus 테스트가 시작되지 않습니다
- spring boot - 100 % 코드 범위로이 코드에 대한 Junit 테스트를 작성하는 방법은 무엇입니까?
- java - intellij에서 junit 테스트를 실행할 수 없습니다 - 재생 버튼이 회색으로 표시됨
- java - @TestFactory에서 생성 한 Junit 동적 테스트를 동시에 실행할 수 있습니까?
- java - 서로 다른 두 가지 테스트에 테스트 러너 사용
- java - Eclipse에서 하나의 클래스를 참조하는 모든 junit 테스트를 실행하는 방법
- junit5 - JUnit 5 테스트를 실행하면 추가 테스트를 등록 할 수 있습니까?
- java - JUnit 테스트 중에 만 JPA 열을 삽입 가능하게 만드는 방법은 무엇입니까?
우선, 당신은 깨끗하게 중지해야합니다
WatchService
완료되면. 이를 수행하고 주석을 추가하는 메소드를 구현하십시오.@PreDestroy
.다음은 사용하지 마십시오
@SpringBootTest
그것은 당신의 테스트에 복잡성과 느린 것 외에는 아무것도 추가하지 않습니다. 대신 직접 인스턴스화하고 적절한 실행기를 사용하여monitor
방법.이와 같은 것은 당신이 원하는 것을 어느 정도 할 것입니다.