Junit 테스트 는 '새 스 레 드 를 시작 합 니 다' 라 는 동작 이 있 을 때 순식간에 끝 나 는 문제 입 니 다.

전에 Future Task 에 관 한 블 로그 한 편 을 썼 습 니 다. http://rainbow702.iteye.com/admin/blogs/2206301
안에 있 는 소스 코드 는 다음 과 같 습 니 다 (이전에 쓴 main 방법 은 포함 되 지 않 습 니 다).
 
public class Preloader {

	private final FutureTask<Long> future = new FutureTask<Long>(new Callable<Long>() {
		@Override
		public Long call() throws Exception {
			Thread.currentThread().setName("Thread(3)");

			System.out.println(Thread.currentThread().getName() + ": simulate a latency ");
			try {
				Thread.sleep(5000);
			} catch (Exception e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + ": the latency is over");
			return Math.round(Math.random() * 1000);
		}
	});

	private final Thread loader = new Thread(future);

	public void start() {
		System.out.println(Thread.currentThread().getName() + ": start the loader");
		loader.start();
		System.out.println(Thread.currentThread().getName() + ": loader started");
	}

	public Long get() {
		try {
			System.out.println(Thread.currentThread().getName() + ": begin to get");
			long start = System.currentTimeMillis();
			Long result = future.get();
			System.out.println(Thread.currentThread().getName() + ": got result: " + result);
			System.out.println(Thread.currentThread().getName() + ": spent time: "
					+ (System.currentTimeMillis() - start));
			return result;
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName() + ": got nothing");
		return null;
	}
}

 당시 작 성 된 JUnit 테스트 코드 는 다음 과 같 습 니 다.
 
 
public class PreloaderTest {

	/**
	 * Test method for {@link com.rainbow.util.futuretask.Preloader#get()}.
	 */
	@Test
	public void testGet() {
		Thread.currentThread().setName("Thread(main)");
		final Preloader pl = new Preloader();
		pl.start();

		// try to get the result before the latency is over
		new Thread(new Runnable() {
			@Override
			public void run() {
				Thread.currentThread().setName("Thread(1)");
				pl.get();
			}
		}).start();

		// try to get the result after the latency is over
		new Thread(new Runnable() {
			@Override
			public void run() {
				Thread.currentThread().setName("Thread(2)");
				try {
					Thread.sleep(6000);
					pl.get();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}).start();
	}
}

 그러나 이 테스트 코드 는 아무리 실행 하고 몇 번 을 실행 하 더 라 도 그 운행 결 과 는 상상 속 의 결과 가 아니 라 다음 과 같은 결과 입 니 다.
 
 
Thread(main): start the loader
Thread(main): loader started
Thread(3): simulate a latency 
Thread(1): begin to get

 결과적으로 Thread (1) Thread (2) Thread (3) 가 실행 도 안 하고 끝 났 습 니 다.
 
 
이 결과 에 대해 매우 의외 라 서 인터넷 에서 찾 아 보 았 는데 다음 과 같은 설명 을 찾 았 다.
 
       ,        ,    Daemon                system.exit  ,        。 eclipse   Junit   org.eclipse.jdt.internal.junit.runner.RemoteTestRunner。        main  。  :

public static void main(String  [] args) {
	try {
		RemoteTestRunner testRunServer= new RemoteTestRunner();
		testRunServer.init(args);
		testRunServer.run();
	} catch (Throwable   e) { 
		e.printStackTrace(); // don't allow System.exit(0) to swallow exceptions
	} finally {
		// fix for 14434
		System.exit(0);
	}
}	

  ,       ,        ,     junit            。

 
이 단락 을 보면 위의 결 과 를 알 수 있다.
 
위의 이런 상황 을 피하 기 위해 내 가 생각 한 두 가지 방법:
① JUnit 을 사용 하지 않 고 스스로 main 방법 을 써 서 테스트 한다. 예 를 들 어 http://rainbow702.iteye.com/admin/blogs/2206301 그 러 하 다
② JUnit 도 사용 하지만 테스트 코드 의 마지막 에 sleep 문 구 를 추가 합 니 다. 즉, 다음 코드 의 마지막 sleep 처럼:
/**
 * 
 */
package com.rainbow.util.futuretask;

import org.junit.Test;

/**
 * @author Rainbow
 */
public class PreloaderTest {

	/**
	 * Test method for {@link com.rainbow.util.futuretask.Preloader#get()}.
	 */
	@Test
	public void testGet() {
		Thread.currentThread().setName("Thread(main)");
		final Preloader pl = new Preloader();
		pl.start();

		// try to get the result before the latency is over
		new Thread(new Runnable() {
			@Override
			public void run() {
				Thread.currentThread().setName("Thread(1)");
				pl.get();
			}
		}).start();

		// try to get the result after the latency is over
		new Thread(new Runnable() {
			@Override
			public void run() {
				Thread.currentThread().setName("Thread(2)");
				try {
					Thread.sleep(6000);
					pl.get();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}).start();

		try {
			Thread.sleep(10000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}

 하지만 이렇게 되면 sleep 이 필요 한 시간 을 정확하게 추산 해 야 한다. 아니면 아예 시간 을 정 하지 않 은 걸 로. sleep()  。

좋은 웹페이지 즐겨찾기