雜糅-mock測試



mock測試就是在測試過程中,對於某些不容易構造或者不容易獲取的對象,用一個虛擬的對象來創建以便測試的測試方法。這個虛擬的對象就是mock對象。mock對象就是真實對象在調試期間的代替品。

使用mock對象測試的關鍵步驟:使用一個接口來描述這個對象 在產品代碼中實現這個接口 在測試代碼中實現這個接口 在被測試代碼中只是通過接口來引用對象,所以它不知道這個引用的對象是真實對象。還是mock對象。

使用Mock Object進行測試,主要是用來模擬那些在應用中不容易構造(如HttpServletRequest必須在Servlet容器中才能構造出來)或者比較複雜的對象(如JDBC中的ResultSet對象)從而使測試順利進行的工具。

目前,在Java陣營中主要的Mock測試工具有JMock,MockCreator,Mockrunner,EasyMock,MockMaker等


如果UserService開發完畢,但UserDao尚未開發或未開發完畢,這時又想測試UserService,那麼就可以通過Mock方式來測試。用EasyMock虛擬一個UserDao對象,然後在虛擬的UserDao上針對UserService方法所需的各方法進行聲明其可能出現的調用結果,也就是聲明UserDao各方法所需的傳入參數和返回結果,最後再調用UserService中的方法(即內部調用了UserDao的方法)並驗證返回結果。

如果對UserService方法的Mock測試全部通過,則表明UserService是編寫正確的

說白了,當我們發現所依賴的對象沒有實現,而此時又想做測試的話,就可以考慮用Mock來做測試


Mock創建方式

createMock-------->此時創建的mock對象在進行verify時僅僅檢查關聯方法是否正常完成調用,只要完成次數一致就認爲測試通過

createNiceMock---->很少使用,略掉

createStrictMock-->與createMock不同的是,它還要驗證關聯方法的調用順序,即verify時要同時驗證完成調用的次數和調用順序


public class UserServiceTest {

@Test

public void testMock(){

//創建DAO的Mock對象

UserDao dao = EasyMock.createMock(UserDao.class);

//進入record階段:當調用dao.load()方法且傳入參數爲Jadyer時,其返回值爲user對象

User user = new User(2,"Jadyer", "hongyu");

//如果UserService.get()裏面調用了兩次dao.load(),那麼這裏就要指定其次數

//EasyMock.expect(dao.load("Jadyer")).andReturn(user).times(2);

EasyMock.expect(dao.load("Jadyer")).andReturn(user);

//進入replay階段

EasyMock.replay(dao);

UserService service = newUserServiceImpl(dao);

User user22 =service.get("Jadyer");

Assert.assertNotNull(user22);

Assert.assertEquals(user22.getId(),user.getId());

Assert.assertEquals(user22.getUsername(), user.getUsername());

Assert.assertEquals(user22.getPassword(), user.getPassword());

//進入verify階段

EasyMock.verify(dao);

}



/**

*測試StrictMock的使用

*/

@Test

public void testStrictMock(){

UserDao dao =EasyMock.createStrictMock(UserDao.class);

User user = new User(2,"Jadyer", "hongyu");

//關鍵在這裏:必須把交互的所有過程都記錄下來,也就是說dao方法被調用了幾次,分別是調用的哪個方法,包括傳的參數及返回值

//若UserServiceImpl.getTwice()中調用兩次load()傳入參數都是Jadyer,那麼下面這兩次的expect()操作便可寫成一行

//EasyMock.expect(dao.load("Jadyer")).andReturn(user).times(2);

EasyMock.expect(dao.load("jadyer")).andReturn(user);

//expectLastCall()是用來操作沒有返回值的方法,此時要先執行dao中沒有返回值的方法,然後再調用expectLastCall()方法

dao.delete("Jadyer");

EasyMock.expectLastCall();

EasyMock.expect(dao.load("Jadyer")).andReturn(user);

EasyMock.replay(dao);

UserService service = newUserServiceImpl(dao);

User user22 =service.list("Jadyer");

Assert.assertNotNull(user22);

Assert.assertEquals(user22.getId(),user.getId());

Assert.assertEquals(user22.getUsername(), user.getUsername());

Assert.assertEquals(user22.getPassword(), user.getPassword());

EasyMock.verify(dao);

}

/**

*使用MocksControl可以檢查一組調用對象之間的關係

*它比較適用於這種情景-->UserService中的某個方法依賴於UserDao和BlogDao等多個對象的情況

*/

@Test

public void testMocksControl(){

//也可以通過Control創建一組Mock對象,如EasyMock.createControl()

IMocksControl control =EasyMock.createStrictControl();

//這時創建的Mock對象就類似於EasyMock.createStrictMock(UserDao.class);

UserDao userDao =control.createMock(UserDao.class);

BlogDao blogDao =control.createMock(BlogDao.class);

blogDao.update("Jadyer");

EasyMock.expectLastCall();

userDao.delete("Jadyer");

EasyMock.expectLastCall();

//讓MocksControl進行操作

control.replay();

new UserServiceImpl(userDao,blogDao).update("Jadyer");

//驗證MocksControl中的所有mock調用

control.verify();

}

/**

*測試添加一個不存在的用戶

*/

@Test

public void testInsertNotExistUser(){

//先做好準備工作

UserDao dao =EasyMock.createStrictMock(UserDao.class);

User user = new User(2,"Jadyer", "hongyu");

UserService service = newUserServiceImpl(dao);

//然後開始EasyMock的測試(先要保證用戶不存在,所以要先andReturn(null))

EasyMock.expect(dao.load(user.getUsername())).andReturn(null);

EasyMock.expect(dao.save(user)).andReturn(user);

EasyMock.replay(dao);

User user22 =service.insert(user);

Assert.assertNotNull(user22);

Assert.assertEquals(user22.getId(),user.getId());

Assert.assertEquals(user22.getUsername(), user.getUsername());

Assert.assertEquals(user22.getPassword(), user.getPassword());

EasyMock.verify(dao);

}

/**

*測試添加一個存在的用戶

* @see爲了查看效果,可以將expected=RuntimeException.class刪去

*/

@Test(expected=RuntimeException.class)

public void testInsertExistUser(){

//先做好準備工作

UserDao dao =EasyMock.createStrictMock(UserDao.class);

User user = new User(2,"Jadyer", "hongyu");

UserService service = newUserServiceImpl(dao);

//然後開始EasyMock的測試(先要保證用戶存在,所以要先andReturn(user))

EasyMock.expect(dao.load(user.getUsername())).andReturn(user);

EasyMock.expect(dao.save(user)).andReturn(user);

EasyMock.replay(dao);

User user22 =service.insert(user);

Assert.assertNotNull(user22);

Assert.assertEquals(user22.getId(),user.getId());

Assert.assertEquals(user22.getUsername(), user.getUsername());

Assert.assertEquals(user22.getPassword(), user.getPassword());

EasyMock.verify(dao);

}

/**

*測試用戶登錄成功

*/

@Test

public void testLoginSuccess(){

//同樣先做好準備工作

UserDao dao =EasyMock.createStrictMock(UserDao.class);

User user = new User(2,"Jadyer", "hongyu");

UserService service = newUserServiceImpl(dao);

//開始測試

//指定測試時所要登錄的用戶名和密碼,由於這裏是要測試登錄成功的情況,所以這裏用戶名密碼就要與準備數據中的相同

String username ="Jadyer";

String password ="hongyu";

//先要保證用戶存在,所以要先andReturn(user)

EasyMock.expect(dao.load(username)).andReturn(user);

EasyMock.replay(dao);

User user22 =service.login(username, password);

Assert.assertNotNull(user22);

Assert.assertEquals(user22.getId(),user.getId());

Assert.assertEquals(user22.getUsername(),user.getUsername());

Assert.assertEquals(user22.getPassword(), user.getPassword());

EasyMock.verify(dao);

}

/**

*測試用戶登錄失敗(用戶不存在)

* @see爲了查看效果,可以將expected=RuntimeException.class刪去

*/

@Test(expected=RuntimeException.class)

public void testLoginFailNotExistUser(){

//同樣先做好準備工作

UserDao dao =EasyMock.createStrictMock(UserDao.class);

UserService service = newUserServiceImpl(dao);

//開始測試

//指定測試時所要登錄的是一個不存在的用戶

String username ="Jaders";

String password ="hongyu";

//爲了保證用戶存在,這裏就要andReturn(null),因爲dao.load一個不存在用戶時取到的是null

EasyMock.expect(dao.load(username)).andReturn(null);

EasyMock.replay(dao);

service.login(username,password);

EasyMock.verify(dao);

}

/**

*測試用戶登錄失敗(用戶密碼錯誤)

* @see爲了查看效果,可以將expected=RuntimeException.class刪去

*/

@Test(expected=RuntimeException.class)

public void testLoginFailPasswordError(){

//同樣先做好準備工作

UserDao dao =EasyMock.createStrictMock(UserDao.class);

User user = new User(2,"Jadyer", "hongyu");

UserService service = newUserServiceImpl(dao);

//開始測試

//指定測試時所要登錄的是一個密碼錯誤的用戶

String username ="Jadyer";

String password ="xuanyu";

//密碼錯誤時用戶是存在的,所以要andReturn(user)

EasyMock.expect(dao.load(username)).andReturn(user);

EasyMock.replay(dao);

service.login(username,password);

EasyMock.verify(dao);

}

}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章