-
@ParameterizedTest사용할 때 java.lang.NoSuchMethodException 발생 시Spring 2022. 2. 16. 21:09
@ParameterizedTest를 사용하여 여러가지 경우를 테스트 하려고 할 때
java.lang.NoSuchMethodException 예외가 발생하게 되었다.
(cannot invoke non-static-method)
원인
@ParameterizedTest @MethodSource("lottoGame") @DisplayName("추첨 번호를 이용하여 올바를 로또 결과를 반환한다.") void match_counts_with_winning_numbers(LottoGame lottoGame, WinningLotto winningLotto, int actual) { //given //when LottoResult lottoResult = lottoGame.draw(winningLotto); //then assertEquals(lottoResult.getResult().get(MatchType.FOUR), actual); assertEquals(lottoResult.getResult().get(MatchType.FIVE), actual); } private Stream<Arguments> lottoGame() { return Stream.of( Arguments.of(new LottoGame(Arrays.asList( new Lotto(new FixNumberStrategy(Arrays.asList(1, 3, 4, 5, 7, 9))), new Lotto(new FixNumberStrategy(Arrays.asList(2, 3, 4, 5, 6, 8)))) ), new WinningLotto(new HashSet<>(Arrays.asList(1, 2, 3, 4, 5, 6)), 1), 1) ); }
해당 예외는 버전이 맞지 않을 때, 파라미터가 맏지 않을 때에도 발생할 수 있지만, 예제를 이용하여 상황을 재구성해서 보면 ParameterizedTest에 사용될 메소드인 lottoGame이 static이 아니라서 발생 되었다. (@MethodSource에 사용될 팩토리 메소드는 static이어야 한다.)
ArgumentSource를 보면 ArgumentProvider는 top-level 클래스 또는 static nested class에 선언되어야 한다 고 나타나있다.
해결 ①
@ParameterizedTest @MethodSource("lottoGame") @DisplayName("추첨 번호를 이용하여 올바를 로또 결과를 반환한다.") void match_counts_with_winning_numbers(LottoGame lottoGame, WinningLotto winningLotto, int actual) { //given //when LottoResult lottoResult = lottoGame.draw(winningLotto); //then assertEquals(lottoResult.getResult().get(MatchType.FOUR), actual); assertEquals(lottoResult.getResult().get(MatchType.FIVE), actual); } private static Stream<Arguments> lottoGame() { return Stream.of( Arguments.of(new LottoGame(Arrays.asList( new Lotto(new FixNumberStrategy(Arrays.asList(1, 3, 4, 5, 7, 9))), new Lotto(new FixNumberStrategy(Arrays.asList(2, 3, 4, 5, 6, 8)))) ), new WinningLotto(new HashSet<>(Arrays.asList(1, 2, 3, 4, 5, 6)), 1), 1) ); }
첫번째 해결방법은 해당 메소드에 static을 넣어주면 해결된다.
해결 ②
@TestInstance(Lifecycle.PER_CLASS) class Test{ @ParameterizedTest @MethodSource("lottoGame") @DisplayName("추첨 번호를 이용하여 올바를 로또 결과를 반환한다.") void match_counts_with_winning_numbers(LottoGame lottoGame, WinningLotto winningLotto, int actual) { //given //when LottoResult lottoResult = lottoGame.draw(winningLotto); //then assertEquals(lottoResult.getResult().get(MatchType.FOUR), actual); assertEquals(lottoResult.getResult().get(MatchType.FIVE), actual); } private Stream<Arguments> lottoGame() { return Stream.of( Arguments.of(new LottoGame(Arrays.asList( new Lotto(new FixNumberStrategy(Arrays.asList(1, 3, 4, 5, 7, 9))), new Lotto(new FixNumberStrategy(Arrays.asList(2, 3, 4, 5, 6, 8)))) ), new WinningLotto(new HashSet<>(Arrays.asList(1, 2, 3, 4, 5, 6)), 1), 1) ); } }
두번째 해결방법은 테스트 클래스 (top-level)에 @TestInstance(Lifecycle.PER_CLASS)를 지정해주어 해당 메서드를 사용할 수 있게 해준다.
( 참고한 사이트 )
https://github.com/junit-team/junit5/issues/1452
https://youtrack.jetbrains.com/issue/IDEA-246118
'Spring' 카테고리의 다른 글
CacadeType.REMOVE 와 orphanRemoval = true의 차이 (0) 2022.02.24 a collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance 발생 시 (0) 2022.02.16 existsBy, countBy (JPA) (0) 2022.02.13 인수테스트 (Acceptance Test) ① 환경 구축 및 작성 (0) 2022.02.08 테스트를 위한 Mock과 그 외의 Test Double (0) 2022.02.03