一段常見的代碼
單元測試是項目的重要組成部分。尤其是對持續發展的產品,單元測試在後期的維護,迴歸有重要等方面有重要作用。
這樣代碼在項目中隨處可見,看看我們應該如何測試
public class NotifyService {
private UserCenter uc;
private MessageCenter mc;
public void sendMessage(long userId, String message) {
String email = uc.getUser(userId).getEmail();
mc.sendEmail(email, message);
}
public void setUc(UserCenter uc) {
this.uc = uc;
}
public void setMc(MessageCenter mc) {
this.mc = mc;
}
}
UserCenter和MessageCenter都是接口,User是一個簡單的JavaBean
由於uc和mc乃外部依賴,此類不需也不應保證uc和mc的正確性,此類只需保證:
假設uc和mc是正確的,那麼我也是正確的。
所以需要隔離依賴--使用mock
使用Mockito
假使使用Mockito,單元測試也許是這個樣子的[需要static import org.mockito.Mockito類的相關方法]
public class NotifyServiceTest {
private NotifyService notifyService;
private UserCenter uc;
private MessageCenter mc;
@Before
public void setUp() {
notifyService = new NotifyService();
uc = mock(UserCenter.class);
mc = mock(MessageCenter.class);
notifyService.setUc(uc);
notifyService.setMc(mc);
}
@Test
public void testSendMessage() {
long userId = 1L;
String email = "foo@bar";
when(uc.getUser(userId)).thenReturn(createUserWithEmail(email));
notifyService.sendMessage(userId, "hello");
verify(mc).sendEmail(eq(email), eq("hello"));
}
private User createUserWithEmail(String email) {
User user = new User();
user.setEmail(email);
return user;
}
}
看到testSendMessage方法
@Test
public void testSendMessage() {
long userId = 1L;
String email = "foo@bar";
when(uc.getUser(userId)).thenReturn(createUserWithEmail(email));
notifyService.sendMessage(userId, "hello");
verify(mc).sendEmail(eq(email), eq("hello"));
}
語義不言自明
測試前,從uc獲得email
測試後,必須調用mc.sendEmail,所以驗證之
小結
通過一個簡單的例子,可以看到:mockito在使我們的測試代碼更直接,語義更明確