Spring

Mockito Mockito.mockStatic()을 사용하여 정적 무효 메서드를 모의합니다.

기록만이살길 2022. 12. 19. 22:35
반응형

Mockito Mockito.mockStatic()을 사용하여 정적 무효 메서드를 모의합니다.

1. 질문(문제점):

저는 Spring Boot를 사용하고 있으며 단위 테스트 중 하나에서 Files.delete(somePath)기능을 조롱해야 합니다. 정적 무효 방법입니다.

Mockito를 사용하면 void 메서드를 조롱할 수 있다는 것을 알고 있습니다.

doNothing().when(MyClass.class).myVoidMethod()

그리고 2020년 7월 10일부터 정적 메서드를 조롱할 수 있습니다.

try (MockedStatic<MyStaticClass> mockedStaticClass = Mockito.mockStatic(MyStaticClass.class)) {
    mockedStaticClass.when(MyStaticClass::giveMeANumber).thenReturn(1L);
    assertThat(MyStaticClass.giveMeANumber()).isEqualTo(1L);
  }

그러나 Files.delete(somePath).

이것은 내 pom.xml 파일입니다(테스트 관련 의존성만 해당).

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-inline</artifactId>
    <version>3.5.15</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>3.5.15</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-junit-jupiter</artifactId>
    <version>3.5.15</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    <version>2.2.6.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-test</artifactId>
    <scope>test</scope>
</dependency>

PowerMockito를 사용하지 않고 정적 무효 메서드를 조롱하는 방법이 있습니까?
가능하다면 올바른 구문은 무엇입니까?

2. 해결방안:

일반적으로 모의 정적 호출은 기본 접근 방식으로 사용되지 않는 최후의 수단입니다.

예를 들어 파일 시스템에서 작동하는 코드를 테스트하는 경우 더 나은 방법이 있습니다. junit예를 들어 버전 에 따라 TemporaryFolder규칙 또는 @TempDir어노테이션 을 사용 합니다.

또한 Mockito.mockStatic테스트 속도가 상당히 느려질 수 있습니다(예: 아래 참고 사항 참조).

위의 주의 사항을 말한 후 테스트 방법을 보여주는 아래 스니펫을 찾으면 해당 파일이 제거됩니다.

class FileRemover {
    public static void deleteFile(Path filePath) throws IOException {
        Files.delete(filePath);
    }
}

class FileRemoverTest {

    @TempDir
    Path directory;

    @Test
    void fileIsRemovedWithTemporaryDirectory() throws IOException {
        Path fileToDelete = directory.resolve("fileToDelete");
        Files.createFile(fileToDelete);

        FileRemover.deleteFile(fileToDelete);

        assertFalse(Files.exists(fileToDelete));
    }

    @Test
    void fileIsRemovedWithMockStatic() throws IOException {
        Path fileToDelete = Paths.get("fileToDelete");
        try (MockedStatic<Files> removerMock = Mockito.mockStatic(Files.class)) {
            removerMock.when(() -> Files.delete(fileToDelete)).thenAnswer((Answer<Void>) invocation -> null);
            // alternatively
            // removerMock.when(() -> Files.delete(fileToDelete)).thenAnswer(Answers.RETURNS_DEFAULTS);

            FileRemover.deleteFile(fileToDelete);

            removerMock.verify(() -> Files.delete(fileToDelete));
        }
    }
}

노트:

  1. Mockito.mockStaticMockito 3.4 이상에서 사용할 수 있으므로 올바른 버전을 사용하고 있는지 확인하십시오.

  2. 스니펫은 의도적으로 두 가지 접근 방식을 보여 @TempDir줍니다 Mockito.mockStatic. 두 테스트를 모두 실행하면 Mockito.mockStatic훨씬 느린 것을 알 수 있습니다. 예를 들어 내 시스템 테스트 Mockito.mockStatic에서 @TempDir.

반응형