ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Junit] Mock과 MockBean
    프로그래밍/Junit 2022. 2. 12. 03:07
    반응형

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

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

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


    1. Mock

    Mock은 Test를 위해 만들어진 가짜 객체입니다. mock객체는 실제 Class에 작성된 메소드를 수행하는 것이 아닌 stub으로 작성한 행위를 수행하여 해당 메소드가 수행된 것처럼 만들 수 있습니다.

     

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

     

    Member Entity
    MemberService
    Member Repository

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

     

    Repository는 DB와 Connection 하여 데이터를 입력 또는 조회하는 담당을 합니다.

     

    DB와 Connection 하여 데이터가 입력되고 조회되는 것은 MemberService의 관심사가 아닙니다.

     

    그런데 Test를 위해 MemberRepository 객체를 생성하고 생성된 Repository를 Service에 주입하게 된다면 Service Test는 관심사가 아닌 것을 위해 DB와 관련된 설정을 추가해야 되는 상황이 발생합니다.

     

    이럴 경우 배보다 배꼽이 더 큰 상황이 벌어지게 됩니다.

     

    그래서 우리는 Repository의 Mock을 이용하여 실제 DB에 저장이 된 것처럼 조회가 된 것처럼 만들어 Service Test에 이용하는 것입니다.

     

    Mock을 생성하는 방법에는 여러 방법이 있습니다.

    • 어노테이션을 이용

      @Mock 어노테이션을 사용하여 Mock 객체로 만들고자 하는 객체를 선언합니다.
      위 Test에서는 MemberRepository를 Mock 객체로 만들고자 하였습니다.

      다음은 @InjectMocks 어노테이션을 이용하여 만들어진 Mock 객체를 주입 입 할 대상 객체를 선언합니다.
      위 Test에서는 MemberService는 MemberRepository를 주입받아야 하므로 MemberService Class에 @InjectMocks를 사용하였습니다.

    • mock메소드 이용

      실행 결과는 어노테이션과 동일 하지만 Mock 객체를 생성하는 방법이 달라졌습니다.
      mock 메소드를 이용하여 Mock 객체로 생성하고자 하는 Class를 파라미터로 전달합니다.
      이것으로 Repository의 Mock 객체를 만들 수 있습니다.

      이제 Service의 객체를 생성할 때 생성자 파라미터로 Mock 객체를 전달하여 Service 객체를 생성합니다.
      이것으로 생성된 Service 객체가 Repository의 메소드를 호출하면 Stub으로 생성한 동작을 수행할 것입니다.
    • 어노테이션과 mock을 혼합 사용
       
      이 경우 Mock 객체는 Test 메소드에서 생성되고 Test 대상인 Service의 경우 Class Level에서 Mock 객체의 주입을 수행하므로 Service 객체가 생성되는 시점에 Mock 객체가 존재하지 않으므로 addMember Test 메소드 수행 시 MemberService 객체의 Repository는 Null인 것을 확인할 수 있습니다.

      이후 Test를 진행하면 Repository가 Null이므로 NullPointException이 발생합니다.

      반대의 경우는 당연히 정상적으로 Test가 가능합니다.

      Class Level에서 Repository의 Mock 객체를 생성하고 해당 객체를 메소드 Level에서 주입하여 Service 객체를 생성하므로 앞선 Test와 동일하게 Test 되는 것을 확인할 수 있습니다.

     

    2. MockBean

    Mock과 MockBean으로 어노테이션이 따로 있는 이유가 분명 존재할 것 입니다.

     

    Mock의 경우는 Test Class에서 만들어 주입할 대상 객체에 Test Class에서 직접 주입하는 작업을 수행하게 됩니다.

    @InjectMocks 또는 생성자 파라미터, Setter 등 을통해 Mock 객체를 주입 합니다.

     

    그러나 Spring의 경우 Spring Context에 등록된 객체 즉 빈의 경우 해당 빈 사용하는 빈은 Spring에 의해 자동으로 주입이 됩니다.

     

    MockBean 또한 Bean이 붙어있는 것으로 보아 유추가 가능합니다. Mock 객체이지만 빈 객체로 만들어 사용하겠다는 것 입니다.

     

    MockBean을 생성하는 방법


    @MockBean 어노테이션을 사용하여 Mock 객체를 Bean으로 만들고자 하는 객체를 선언합니다.
    Test에서는 MemberRepository를 MockBean으로 만들었습니다.

     

    Spring에서는 @AutoWired 어노테이션을 통해 Spring Context에 등록된 Bean 객체를 주입 받아 사용할 수 있습니다.

    하여 Test에서도 MemberService 객체를 주입 받아 사용할 수 있도록 AutoWired를 이용하여 주입 받았습니다.

     

    MemberService는 MemberRepository 객체를 사용하므로 MockBean으로 등록된 MemberRepository 객체를 주입 받은 Service 객체를 Spring이 memberService 변수에 주입하여 줍니다.

     

    이후 Test 진행의 경우 위 Mock 과 동일하게 진행되는 것을 확인할 수 있습니다.

     

    MockBean의 경우는 메소드를 통해 생성하는 방법은 없으며 어노테이션을 이용하여 생성이 가능 합니다.

     

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

    반응형

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

    [Junit] doReturn과 thenReturn  (0) 2022.02.21
    [Junit] Test Double Spy 상세  (1) 2022.02.14
    [Junit] Test Double  (0) 2022.02.08
    [Junit] Junit5 Exception Throw 테스트  (0) 2021.12.28

    댓글

Designed by Tistory.