티스토리 뷰

Java

[Java] Mockito BDD (Behavior Driven Development)

snail voyager 2024. 6. 2. 14:26
728x90
반응형

BDD (Behavior Driven Development)

https://en.wikipedia.org/wiki/Behavior-driven_development

BDD(Behavior Driven Development)은 소프트웨어 개발 방법론의 하나로, 개발자와 비개발자(예: 비즈니스 분석가, 품질 관리자)가 협력하여 소프트웨어의 기능을 정의하고, 그 기능의 동작을 명확하게 이해하고 검증할 수 있도록 돕는 것을 목표로 합니다. BDD는 TDD(Test Driven Development)에서 발전한 개념으로, 사용자 스토리를 기반으로 한 테스트 작성에 중점을 둡니다. BDD는 개발 과정에서 커뮤니케이션을 강화하고, 모든 이해관계자가 소프트웨어의 동작을 명확하게 이해할 수 있도록 하는 데 중점을 둡니다.

 

  • 유저 스토리는 비즈니스 요구 사항을 설명하는 간단한 문장 형태의 설명입니다.
    • "As a [role], I want [feature] so that [benefit]" 형식으로 작성됩니다.
    • 예: "As a user, I want to log in so that I can access my account."
  • 시나리오는 유저 스토리의 구체적인 동작을 정의하는 예제로, Given-When-Then(GWT) 형식을 사용합니다.

BDDMockito

stubbing으로 사용하던 when 메서드는 Given-When-Then 형식에 어울리지 않기 때문에 

BDDMockito에서는 given 메서드로 사용한다.

 import static org.mockito.BDDMockito.*;

 Seller seller = mock(Seller.class);
 Shop shop = new Shop(seller);

 public void shouldBuyBread() throws Exception {
   //given
   given(seller.askForBread()).willReturn(new Bread());

   //when
   Goods goods = shop.buyBread();

   //then
   assertThat(goods, containBread());
 }

willReturn()

Mockito BDD Style에서 특정 메서드 호출에 대해 반환값을 설정할 때 사용되는 메서드

thenReturn()과 유사한 역할을 하며, BDD 스타일의 가독성을 높이기 위해 설계됨

BDD 스타일의 Mockito 메서드인 given()과 함께 사용

간단한 반환 값 설정

//기존 when().thenReturn() 방식
when(mock.someMethod()).thenReturn("value");

//BDD 스타일의 given().willReturn() 방식
given(mock.someMethod()).willReturn("value");

여러 값 반환

@Test
void testMultipleWillReturn() {
    MyService mockService = mock(MyService.class);

    // 순차적으로 반환값 설정
    given(mockService.process()).willReturn("first", "second", "third");

    // 첫 번째 호출
    assertEquals("first", mockService.process());
    // 두 번째 호출
    assertEquals("second", mockService.process());
    // 세 번째 호출
    assertEquals("third", mockService.process());
}

Exception throwable

   //given
   willThrow(new RuntimeException("boo")).given(mock).foo();

   //when
   Result result = systemUnderTest.perform();

   //then
   assertEquals(failure, result);

BDDMockito.then()

Mockito.verify()와 유사하게 동작하며, 특정 메서드 호출이 예상대로 발생했는지를 검증

https://javadoc.io/static/org.mockito/mockito-core/5.11.0/org/mockito/BDDMockito.Then.html

  • then(T mock).should(): 기본적인 메서드 호출 검증을 수행합니다.
  • then(T mock).should(times(int)): 지정된 횟수만큼 메서드가 호출되었는지 검증합니다.
  • then(T mock).shouldHaveNoMoreInteractions(): 이전에 검증된 메서드 호출 외에 더 이상의 상호작용이 없었는지 검증합니다.
  • then(T mock). shouldHaveNoInteractions(): 주로 객체가 전혀 호출되지 않았음을 확인할 때 사용
    shouldHaveZeroInteractions는 shouldHaveNoInteractions의 더 직관적인 이름
   person.ride(bike);
   person.ride(bike);

   then(person).should(times(2)).ride(bike);
   then(person).shouldHaveNoMoreInteractions();
   then(police).shouldHaveZeroInteractions();

Mockito InOrder

메서드 호출의 순서를 검증하는 데 사용

import static org.mockito.Mockito.*;
import static org.mockito.BDDMockito.*;

import java.util.List;

import org.junit.Test;
import org.mockito.InOrder;

public class InOrderMultipleMocksTest {
    @Test
    public void testInOrderMultipleMocks() {
        // Given
        List<String> mockedList1 = mock(List.class);
        List<String> mockedList2 = mock(List.class);

        // When
        mockedList1.add("first");
        mockedList2.add("second");
        mockedList1.add("third");

        // Then
        InOrder inOrder = inOrder(mockedList1, mockedList2);
        inOrder.verify(mockedList1).add("first");
        inOrder.verify(mockedList2).add("second");
        inOrder.verify(mockedList1).add("third");
    }
}

inOrder(Object... mocks): InOrder 객체를 생성합니다.
verify(T mock): InOrder 객체를 사용하여 특정 순서로 메서드 호출을 검증합니다.

BDD Style InOrder

   InOrder inOrder = inOrder(person);

   person.drive(car);
   person.ride(bike);
   person.ride(bike);

   then(person).should(inOrder).drive(car);
   then(person).should(inOrder, times(2)).ride(bike);

 

 

 

https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#19

https://javadoc.io/static/org.mockito/mockito-core/5.11.0/org/mockito/BDDMockito.html

 

 

728x90
반응형
반응형
300x250