통합 테스트 스위트가 있습니다. IntegrationTestBase
모든 시험을 연장 할 수있는 수업이 있습니다. 이 기본 클래스에는 API 및 DB 연결을 설정 하는 @Before
( public void setUp()
) 및 @After
( public void tearDown()
) 메소드가 있습니다. 내가 해왔 단지 각 테스트 케이스에서 그 두 가지 방법을 무시하고 호출 super.setUp()
하고 super.tearDown()
. 그러나 누군가가 수퍼에게 전화하는 것을 잊거나 잘못된 장소에두면 예외가 발생하고 마지막으로 또는 뭔가를 슈퍼라고 부르는 것을 잊어 버린 경우 문제가 발생할 수 있습니다.
내가하고 싶은 것은 만들 것입니다 setUp
및 tearDown
기본 클래스의 메소드를 final
다음 단지 우리 자신의 주석 추가 @Before
및 @After
방법을. 초기 테스트를 수행하면 항상 다음 순서로 호출되는 것으로 보입니다.
Base @Before
Test @Before
Test
Test @After
Base @After
하지만 주문이 보장되지 않아 문제가 발생할 수 있다고 우려합니다. 나는 둘러 보았고 주제에 대해 아무것도 보지 못했습니다. 내가 할 수 있고 문제가 없는지 아는 사람이 있습니까?
암호:
public class IntegrationTestBase {
@Before
public final void setUp() { *always called 1st?* }
@After
public final void tearDown() { *always called last?* }
}
public class MyTest extends IntegrationTestBase {
@Before
public final void before() { *always called 2nd?* }
@Test
public void test() { *always called 3rd?* }
@After
public final void after() { *always called 4th?* }
}
답변
예,이 동작은 보장됩니다.
@Before
수퍼 클래스 의 메소드는 현재 클래스에서 대체되지 않는 한 현재 클래스 의 메소드보다 먼저 실행됩니다. 다른 순서는 정의되어 있지 않습니다.
@After
수퍼 클래스에 선언 된 메소드는 현재 클래스에서 재정의되지 않는 한 현재 클래스 의 메소드 이후에 실행됩니다.
답변
전에 나를 물린 한 가지 잠재력이 있습니다.
@Before
클래스 @Before
내에서 정의 된 메소드 를 실행하는 순서 가 보장되지 않기 때문에 각 테스트 클래스마다 최대 하나의 메소드 를 갖고 싶습니다 . 일반적으로 이러한 메소드를 호출합니다 setUpTest()
.
그러나 @Before
로 문서화되어 있지만 The @Before methods of superclasses will be run before those of the current class. No other ordering is defined.
이것은 @Before
클래스 계층에서 고유 한 이름을 가진 각 메소드 가있는 경우에만 적용됩니다 .
예를 들어, 나는 다음을 가졌다 :
public class AbstractFooTest {
@Before
public void setUpTest() {
...
}
}
public void FooTest extends AbstractFooTest {
@Before
public void setUpTest() {
...
}
}
나는 AbstractFooTest.setUpTest()
전에 달릴 것으로 예상 FooTest.setUpTest()
했지만 FooTest.setupTest()
처형되었다. AbstractFooTest.setUpTest()
전혀 호출되지 않았습니다.
작동하려면 코드를 다음과 같이 수정해야합니다.
public void FooTest extends AbstractFooTest {
@Before
public void setUpTest() {
super.setUpTest();
...
}
}
답변
나는의 문서를 기반으로 생각 @Before
하고 @After
올바른 결론은 방법에게 고유 한 이름을 제공하는 것입니다. 테스트에서 다음 패턴을 사용합니다.
public abstract class AbstractBaseTest {
@Before
public final void baseSetUp() { // or any other meaningful name
System.out.println("AbstractBaseTest.setUp");
}
@After
public final void baseTearDown() { // or any other meaningful name
System.out.println("AbstractBaseTest.tearDown");
}
}
과
public class Test extends AbstractBaseTest {
@Before
public void setUp() {
System.out.println("Test.setUp");
}
@After
public void tearDown() {
System.out.println("Test.tearDown");
}
@Test
public void test1() throws Exception {
System.out.println("test1");
}
@Test
public void test2() throws Exception {
System.out.println("test2");
}
}
결과적으로 주다
AbstractBaseTest.setUp
Test.setUp
test1
Test.tearDown
AbstractBaseTest.tearDown
AbstractBaseTest.setUp
Test.setUp
test2
Test.tearDown
AbstractBaseTest.tearDown
이 방법의 장점 : AbstractBaseTest 클래스의 사용자는 실수로 setUp / tearDown 메소드를 대체 할 수 없습니다. 그들이 원한다면 정확한 이름을 알아야 할 수 있습니다.
이 접근 방식의 단점 : 사용자는 setUp / tearDown 이전 또는 이후에 발생하는 상황을 알 수 없습니다. 그들은 이러한 것들이 추상 클래스에 의해 제공된다는 것을 알아야합니다. 그러나 그것이 추상적 클래스를 사용하는 이유라고 생각합니다.
답변
상황을 바꾸면 기본 클래스 추상을 선언하고 자손이 기본 클래스의 주석이 달린 setUp 및 tearDown 메서드에서 호출되는 setUp 및 tearDown 메서드 (주석없이)를 선언하도록 할 수 있습니다.
답변
@BeforeClass
주석을 사용 하여 setup()
항상 먼저 호출 되도록 할 수 있습니다 . 마찬가지로 @AfterClass
주석을 사용 하여 tearDown()
항상 마지막에 호출 되도록 할 수 있습니다 .
이것은 일반적으로 권장되지 않지만 지원됩니다 .
정확히 원하는 것은 아니지만 테스트가 실행되는 동안 DB 연결을 기본적으로 열어 놓은 다음 끝까지 한 번에 닫으십시오.
답변
이것은 태그 라인 질문에 대한 답변이 아니지만 질문 본문에 언급 된 문제에 대한 답변입니다. @Before 또는 @After를 사용하는 대신 @ org.junit.Rule 을 사용 하면 유연성이 향상됩니다. 연결을 관리하는 경우 ExternalResource (4.7 현재)가 가장 관심이있는 규칙입니다. 또한 규칙의 실행 순서를 보장하려면 RuleChain (4.10 기준)을 사용하십시오. 이 질문을 받았을 때이 모든 것이 가능하다고 생각합니다. 아래 코드 예제는 ExternalResource의 javadoc에서 복사되었습니다.
public static class UsesExternalResource {
Server myServer= new Server();
@Rule
public ExternalResource resource= new ExternalResource() {
@Override
protected void before() throws Throwable {
myServer.connect();
};
@Override
protected void after() {
myServer.disconnect();
};
};
@Test
public void testFoo() {
new Client().run(myServer);
}
}