BDD 简介

描述

BDD

given some preconditions (Arrange)
when an action occurs (Act)
then verify the output (Assert)

行为驱动开发

  1. given(Arrange): 布置环境
  2. when(Act): 表演
  3. then(Assert): 然后检查

Code

准备相关类

public class PhoneBookRepository {
  private final HashMap<String, String> mHashMap = new HashMap<>();

  public boolean contains(String name) {
    return mHashMap.containsKey(name);
  }

  public void insert(String name, String phone) {
    mHashMap.put(name, phone);
  }

  public String getPhoneNumberByContactName(String name) {
    return mHashMap.get(name);
  }
}
public class PhoneBookService {
  private final PhoneBookRepository phoneBookRepository ;

  public PhoneBookService(PhoneBookRepository phoneBookRepository) {this.phoneBookRepository = phoneBookRepository;}

  public void register(String name, String phone) {
    if (!name.isEmpty() && !phone.isEmpty()
        && !phoneBookRepository.contains(name)) {
      phoneBookRepository.insert(name, phone);
    }
  }

  public String search(String name) {
    if (!name.isEmpty() && phoneBookRepository.contains(name)) {
      return phoneBookRepository.getPhoneNumberByContactName(name);
    }
    return null;
  }
}

BDD风格的测试

@RunWith(JUnit4.class)
public class PhoneBookServiceTest {
  private PhoneBookRepository phoneBookRepository;
  private String momContactName;
  private PhoneBookService phoneBookService;
  private String momPhoneNumber;

  @Before
  public void before() {
    momContactName = "Hello";
    momPhoneNumber = "123";
    phoneBookRepository = mock(PhoneBookRepository.class);
    phoneBookService = new PhoneBookService(phoneBookRepository);
  }

  @Test
  public void testBDD() {
    given(phoneBookRepository.contains(momContactName))
        .willReturn(false);

    phoneBookService.register(momContactName, momPhoneNumber);

    then(phoneBookRepository)
        .should()
        .insert(momContactName, momPhoneNumber);
  }

mock返回值

  @Test
  public void returnValue() {
    given(phoneBookRepository.contains(momContactName))
        .willReturn(false);

    String xContactName = "Hello";
    phoneBookService.register(xContactName, "");

    then(phoneBookRepository)
        .should(never())
        .insert(momContactName, momPhoneNumber);
  }

mock动态返回值

  @Test
  public void returnDynamic() {
    given(phoneBookRepository.contains(momContactName))
        .willReturn(true);
    given(phoneBookRepository.getPhoneNumberByContactName(momContactName))
        .will((InvocationOnMock invocation) ->
            invocation.getArgument(0).equals(momContactName)
                ? momPhoneNumber
                : null);
    phoneBookService.search(momContactName);
    then(phoneBookRepository)
        .should()
        .getPhoneNumberByContactName(momContactName);
  }

mock抛异常

  @Test
  public void testException() {
    String xContactName = "hahha";
    given(phoneBookRepository.contains(xContactName))
        .willReturn(false);
    String tooLongPhoneNumber = "111111111111";
    willThrow(new RuntimeException())
        .given(phoneBookRepository)
        .insert(any(String.class), eq(tooLongPhoneNumber));

    try {
      phoneBookService.register(xContactName, tooLongPhoneNumber);
      fail("Should throw exception");
    } catch (RuntimeException ignore) {
    }

    then(phoneBookRepository)
        .should(never())
        .insert(momContactName, tooLongPhoneNumber);
  }
}

注意willThrow放在given前面了,因为given要mock的方法是void的,无法捕获

posted @ 2021-07-05 00:00  yupenglei  阅读(317)  评论(0)    收藏  举报