描述
BDD
given some preconditions (Arrange)
when an action occurs (Act)
then verify the output (Assert)
行为驱动开发
- given(Arrange): 布置环境
- when(Act): 表演
- 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的,无法捕获