ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Junit] Test Double Spy 상세
    프로그래밍/Junit 2022. 2. 14. 23:37
    반응형

    이 글은 혼자 학습한 내용을 바탕으로 작성되었습니다.

    틀리거나 잘못된 정보가 있을 수 있습니다.

    댓글로 알려주시면 수정하도록 하겠습니다.


    1. Spy와 Mock 차이

    Spy는 Mock과 동일하게 Test를 위해 만들어진 객체입니다. 그러나 Mock과는 다른 점이 존재합니다.

     

    Mock의 경우는 Test를 위해 실 객체의 겉모양(Class)만 가지고 있으며 속(Method)의 경우 Stub을 통해 동작할 내용을 지정하여야 합니다.

     

    그러나 Spy의 경우는 실제 객체와 동일한 겉모양(Class) 뿐만 아니라 구현 또한 동일하게 동작합니다.

     

    또한 실제 구현된 내용 중 일부분을 Stub을 통해 Test 내용으로 변경 또한 가능합니다.

     

    작성한 Class들을 확인해 보겠습니다.

     

    FileService

    FileService Class를 보면 생성자로 AttachFileRepository를 주입받아 Service가 동작되도록 구현되어 있습니다.

     

    파일 정보 변경 중 isDelete Flag가 true 인 경우 DB의 데이터를 제거하고 해당 file 또한 제거하도록 하고자 하였습니다.

     

    FileServiceTest

    Spy설명을 위해 먼저 Mock으로 생성된 Repository를 주입받은 FileService의 Test를 진행하도록 하겠습니다.

     

    위 Test를 진행한 결과 위 결과처럼 true를 반환할 것이라 예상하였지만 결과는 false를 반환한 것을 확인할 수 있습니다.

     

    이유는 파일을 제거하고자 하는 위치에 test.txt 파일이 존재하지 않기 때문에 file.delete() 메소드가 false를 반환하여 Test가 실패하는 것입니다.

     

    그럼 FileService의 deleteFile 메소드를 Mocking 하여 파일의 존재 여부와 상관없이 파일이 정상 제거된 것처럼 true를 반환하도록 하면 Test는 정상적으로 진행될 것 같습니다.

     

    FileServiceTest 2

    위 Test처럼 doReturn을 이용하여 deleteFile 메소드 실행 시 true가 반환될 수 있도록 Mocking을 작성하였습니다.

     

    하지만 위 결과처럼 Test가 실패하는 것을 확인할 수 있습니다. 이유는 FileService의 경우 Mock 객체가 아니므로 Mocking을 작성할 수 없기 때문입니다.

     

    InjectMocks로 생성된 객체의 경우 Mock객체를 주입받은 실제 객체이지 Mock객체가 아닙니다. 그러므로 해당 객체의 메소드 또한 Mocking이 불가능한 것입니다.

     

    그럼 이번 Test는 진행을 할 수 없는 것일까요?

     

    지금 필요한 것이 바로 Spy입니다. Spy의 경우는 실 객체와 동일한 겉모양(Class) 뿐만 아니라 구현 또한 동일하다고 처음 설명 드렸습니다.

     

    다만 Spy는 일부 메소드에 대하여 Mocking이 가능 한 점이 바로 Mock 객체와 다른 점 입니다.

     

    이제 FileService를 Spy객체로 만들어 deleteFile 메소드를 Mocking 하도록 해보겠습니다.

     

    FileServiceTest 3

    Test가 실패하던 코드에서 FileService에 @Spy 어노테이션만 추가 하여 Test를 진행 하도록 하겠습니다.

     

    위 처럼 Test가 정상적으로 완료되는 것을 확인할 수 있습니다.

     

    이유는 FileService를 Spy객체로 만들어 Test하고자 하는 메소드 updateFile의 경우 실 구현과 동일하게 동작을 하며 deleteFile 메소드는 Mocking으로 작성한 true를 반환하도록 하였기 때문입니다.

     

    사용된 예제 코드는 Git에 있습니다.

    반응형

    '프로그래밍 > Junit' 카테고리의 다른 글

    [Junit] doReturn과 thenReturn  (0) 2022.02.21
    [Junit] Mock과 MockBean  (0) 2022.02.12
    [Junit] Test Double  (0) 2022.02.08
    [Junit] Junit5 Exception Throw 테스트  (0) 2021.12.28

    댓글

Designed by Tistory.