여기에있는 대부분의 답변이 상당히 구식이기 때문에이 질문에 업데이트 된 답변이 필요하다고 생각합니다.
먼저 OP의 질문에 :
나는 JUnit에 "예상 된 예외"개념을 도입하는 것이 나쁜 움직임이라는 것을 꽤 잘 받아 들였다고 생각한다. 그 예외는 어디에서나 발생할 수 있고 테스트를 통과 할 것이기 때문이다. 매우 도메인 특정 예외를 던지고 주장하는 경우 작동하지만 절대적으로 완전해야하는 코드를 작업 할 때만 이러한 종류의 예외를 던집니다. 대부분의 APIS는 단순히 IllegalArgumentException
또는 IllegalStateException
. 두 번의 호출이 이러한 예외를 잠재적으로 던질 수 @ExpectedException
있다면, 예외를 던지는 잘못된 행이 있더라도 주석은 테스트를 녹색 막대로 표시합니다!
이 상황을 위해 나는 여기에 많은 다른 사람들이 작성했다고 확신하는 클래스를 작성했습니다 assertThrows
.
public class Exceptions {
private Exceptions(){}
public static void assertThrows(Class<? extends Exception> expectedException, Runnable actionThatShouldThrow){
try{
actionThatShouldThrow.run();
fail("expected action to throw " + expectedException.getSimpleName() + " but it did not.");
}
catch(Exception e){
if ( ! expectedException.isInstance(e)) {
throw e;
}
}
}
}
이 메소드는 예외가 발생하면 단순히 반환하므로 테스트에서 추가 주장 / 확인을 수행 할 수 있습니다.
Java 8 구문을 사용하면 테스트가 정말 멋지게 보입니다. 다음은이 방법을 사용하는 모델에 대한 더 간단한 테스트 중 하나입니다.
@Test
public void when_input_lower_bound_is_greater_than_upper_bound_axis_should_throw_illegal_arg() {
AxisRange range = new AxisRange(0,100);
Runnable act = () -> range.setLowerBound(200);
assertThrows(IllegalArgumentException.class, act);
}
이 테스트는 "act"단계가 실제로 어떤 작업도 수행하지 않기 때문에 약간 불안정하지만 의미는 여전히 상당히 명확하다고 생각합니다.
또한 예외가 발생하는지 확인하기 위해 mockito 스타일 구문을 사용하는 catch-exception 이라는 maven에 작은 라이브러리가 있습니다. 예쁘게 보이지만 동적 프록시의 팬은 아닙니다. 즉, 구문이 너무 매끄 럽기 때문에 여전히 유혹적입니다.
List myList = new ArrayList();
catchException(myList).get(1);
assert caughtException() instanceof IndexOutOfBoundsException;
마지막으로이 스레드에 도달하기 위해 발생한 상황에 대해 일부 조건이 충족되면 테스트 를 무시할 수 있는 방법 이 있습니다.
지금은 JNA라는 자바 네이티브 라이브러리 로딩 라이브러리를 통해 일부 DLL을 호출하고 있지만 빌드 서버는 우분투에 있습니다. 나는 JUnit 테스트로 이런 종류의 개발을 추진하는 것을 좋아합니다. 비록 지금은 "단위"와는 거리가 멀지 만요. 내가하고 싶은 것은 로컬 컴퓨터에 있으면 테스트를 실행하고 우분투에 있으면 테스트를 무시하는 것입니다. JUnit 4에는 다음과 같은 조항이 있습니다 Assume
.
@Test
public void when_asking_JNA_to_load_a_dll() throws URISyntaxException {
Assume.assumeFalse(BootstrappingUtilities.isCircleCI());
URL url = DLLTestFixture.class.getResource("USERDLL.dll");
String path = url.toURI().getPath();
path = path.substring(0, path.lastIndexOf("/"));
NativeLibrary.addSearchPath("USERDLL", path);
Object dll = Native.loadLibrary("USERDLL", NativeCallbacks.EmptyInterface.class);
assertThat(dll).isNotNull();
}