서론

기존에 jar파일을 추가해서 Junit4로 테스트하던 프로젝트를 마찬가지로 jar파일을 Junit5로 버전 업해서 사용하고 있었는데
‘굳이 이럴 필요없이 maven 프로젝트로 변경하면 되지 않나?’라는 생각에 maven 프로젝트로 변경 후 발생했던 에러를 해결한 방법을 작성해둔다…

상황

위에서 적은 것 처럼 기존에 Junit jar를 다운받아서 직접 경로를 지정하는 방식으로 junit4, 5를 둘 다 사용하고 있었는데 프로젝트를 maven으로 변경 후 의존성 충돌이 발생해 아래와 같은 에러가 발생하며 테스트가 진행되지 않았다.

발생한 에러

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Internal Error occurred.
org.junit.platform.commons.JUnitException: TestEngine with ID 'junit-vintage' failed to discover tests
at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discoverEngineRoot(EngineDiscoveryOrchestrator.java:111)
at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discover(EngineDiscoveryOrchestrator.java:85)
at org.junit.platform.launcher.core.DefaultLauncher.discover(DefaultLauncher.java:92)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:75)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)
Caused by: org.junit.platform.commons.JUnitException: Unsupported version of junit:junit: 3.8.1. Please upgrade to version 4.12 or later.
at org.junit.vintage.engine.JUnit4VersionCheck.checkSupported(JUnit4VersionCheck.java:49)
at org.junit.vintage.engine.JUnit4VersionCheck.checkSupported(JUnit4VersionCheck.java:35)
at org.junit.vintage.engine.VintageTestEngine.discover(VintageTestEngine.java:62)
at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discoverEngineRoot(EngineDiscoveryOrchestrator.java:103)
... 7 more

Process finished with exit code -2

위 에러 로그처럼 ‘junit-vintage’를 아이디로 하는 테스트 엔진을 찾지 못했다는 에러가 발생해서 junit-vintage 의존성을 추가해주었는데..


그 후 삽질

1
2
3
4
5
6
7
<!-- https://mvnrepository.com/artifact/org.junit.vintage/junit-vintage-engine -->
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>5.7.1</version>
<scope>test</scope>
</dependency>

추가 해줘도 똑같은 에러만 반복 할 뿐이었다.

그래서 공식 문서를 살펴보니..

JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage

라고 떡하니 써 적혀있어서 위에 3 개의 의존성을 모두 추가한 후 리빌드 후 다시 테스트를 실행해봤다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- Only needed to run tests in a version of IntelliJ IDEA that bundles older versions -->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<version>1.7.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.7.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>5.7.1</version>
<scope>test</scope>
</dependency>

하지만 결과는 마찬가지였고… .m2폴더에서 Junit 의존성을 다 삭제하고, Intellij project setting에서 Modules, Libraies에서 모두 삭제하고 이것저것 다 해봤지만 모두 실패로 돌아가서 결국 새 maven 프로젝트를 만들어서 하나씩 비교해보기로 했다.


해결

그 결과… .iml 파일에 아래 처럼 의존성들이 남아있는 것을 확인했고…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<orderEntry type="module-library" scope="TEST">
<library name="JUnit5.4">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/junit/jupiter/junit-jupiter/5.4.2/junit-jupiter-5.4.2.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/junit/jupiter/junit-jupiter-api/5.4.2/junit-jupiter-api-5.4.2.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/apiguardian/apiguardian-api/1.0.0/apiguardian-api-1.0.0.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/opentest4j/opentest4j/1.1.1/opentest4j-1.1.1.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/junit/platform/junit-platform-commons/1.4.2/junit-platform-commons-1.4.2.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/junit/jupiter/junit-jupiter-params/5.4.2/junit-jupiter-params-5.4.2.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/junit/jupiter/junit-jupiter-engine/5.4.2/junit-jupiter-engine-5.4.2.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/junit/platform/junit-platform-engine/1.4.2/junit-platform-engine-1.4.2.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-api:5.7.1" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.apiguardian:apiguardian-api:1.1.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.opentest4j:opentest4j:1.2.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.platform:junit-platform-commons:1.7.1" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-engine:5.7.1" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.platform:junit-platform-engine:1.7.1" level="project" />

모든 의존성을 삭제 후 다시 Junit5만 의존성 추가하여 테스트를 실행하니…

드디어 성공적인 테스트를 완료 할 수 있었다.

여담

project setting에서 분명 모듈 관련된 설정을 모두 삭제 했는데 왜 .iml파일에 설정이 삭제되지 않고 남아있는진 모르겠지만, 필자와 같은 상황이 발생하는 다른 사람들에게 도움이 되길 바라며 글을 마무리한다.

댓글 공유

결론

  • Synchronous, Asynchronous 는 두 개 이상의 대상에 대한 시간을 관리하는 방법이고,
  • Blocking, Non-Blocking 은 직접 제어 할 수 없는 대상을 처리하는 방법에 대한 것이다.

Synchronous, Asynchronous

  • 두 개 이상의 대상들의 시간을 처리하는 방식
  • Synchronous는 두 개 이상의 대상들의 시간을 일치 시키는 것 으로 메서드가 종료되는 시간과 결과를 전달받은 시간이 일치하면 Synchronous(동기) 방식이다.
  • Asynchronous는 두 개 이상의 대상들의 시간을 일치 시키지 않는 것 으로 메서드가 종료되는 시간과 결과를 전달받은 시간이 일치하지 않으면 Asynchronous(비동기) 방식이다.

Blocking, Non-Blocking

  • 직접 제어 할 수 없는 대상에 대한 처리 방식
  • Blocking은 직접 제어 할 수 없는 대상이 작업이 끝날 때 까지 제어권을 넘기지 않아 작업이 끝날 때 까지 대기 하는 방식이다.
  • Non-Blocking은 직접 제어 할 수 없는 대상의 작업의 종료와 관계없이 제어권을 바로 다시 얻어와 다른 일을 할 수 있게 하는 방식이다.

본론

Synchronous

우선 Synchronous의 뜻을 사전에선 아래와 같이 정의하고 있다.

동시 발생하는

네이버 어학사전

이 처럼 두 개 이상의 작업을 동시에 발생시키거나, 동시에 종료시키는 행동을 말한다.

동기 방식을 사용 할 경우 메서드를 호출 했을 때, 결과를 호출한 쪽에서 스스로 확인하고 처리하기 때문에, 결과를 처리 할 때까지 기다렸다가 결과를 전달받고 메서드를 종료 시킨다.

간단히 요약하면 메서드를 호출하면 그 메서드가 종료되는 시간과 결과가 return 되는 시간이 같다는 것으로, 메서드가 종료되는 시간과 결과가 return 되는 시간이 같으므로 동기 방식이라 말한다.

혹은, 2개 이상의 일을 각각 실행시켜 A가 끝나는 시간과 B가 시작하는 시간이 같은 경우도 마찬가지로 동기 방식이라고 할 수 있다.

Java로 예를 들면 쓰레드를 동기 시키기 위해 사용하는 synchronized가 있고 일반적으로는 일부러 설정하지 않는 한 보통의 메서드 호출은 모두 동기 방식으로 사용된다.

Asynchronous

Asynchronous, 비동기 방식은 부정형 접두사 A를 붙여서 두 개 이상의 대상의 시간을 일치 시키지 않는 방식으로 동기 방식과 반대로 동작한다.

즉, 메서드를 호출 했을 때 결과가 return되지 않더라도 다른 작업을 수행하거나 메서드를 종료하고 나중에 처리되면 그 때 결과물을 가져온다.

이 때 메서드를 호출한 시간과 return된 결과를 받은 시간이 일치하지 않으므로 이러한 방식을 비동기 방식이라 한다.

보통 ajax를 통해 많이 사용 해봤을 것이고, Java에선 쓰레드를 활용해 비동기적으로 처리 할 수 있고, Spring에선 @Async Annotation을 이용해 비동기 방식을 처리 할 수 있다.

Blocking

결론에서 말한 것 처럼 Blocking은 직접 제어 할 수 없는 대상이 작업이 끝날 때 까지 제어권을 넘기지 않아 작업이 끝날 때 까지 대기하게 하는 방식이다.

예를 들면 스타크래프트에서 테란의 SCV는 한번 건물을 짓기 시작하면 건설이 끝날 때 까지 다른 동작을 할 수 없으므로, Blocking 상태라고 할 수 있고, Java에선 System.in 같은 I/O 처리를 예로 들 수 있다.

Non-Blocking

Blocking과 반대되는 방식으로 작업의 처리 여부와 상관없이 작업을 호출한 쪽이 다시 제어권을 가져와서 자유롭게 다른 일을 처리할 수 있는 방식을 Non-Blocking 방식이라고 한다.

마찬가지의 예로 프로토스의 프로브는 건물을 짓게 하면 차원 균열만 개방하고 바로 미네라를 캐는 등의 다른 일을 수행 할 수 있으므로 프로브는 Non-Blocking 상태라고 할 수 있다.


서플라이디포를 건설 하는 동안 다른 행위를 할 수 없는 SCV
첫 번째 파일럿을 소환 후 파일럿이 완성되기 전에 두 번째 파일럿을 소환 할 수 있는 프로브

참고 사이트

댓글 공유

  • page 1 of 1

Junggu Ji

author.bio


author.job