欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

大話重構連載15:采用Mock技術完成測試

系統 1640 0
第五次重構我們引入了數據庫的設計,用戶信息要從數據庫中讀取,問候語庫存儲在數據庫中,并支持添加與更新。數據庫的引入使自動化測試變得困難了,因為數據狀態總是變化著的,而這種變化使得測試過程不能復現,這是我們不愿看到的。因此,我們在設計時將業務與數據庫訪問分離,形成了UserDao與GreetingRuleDao。此時,我們的設計應當遵從“依賴反轉”原則,即將UserDao與GreetingRuleDao設計成接口,并編寫它們的實現UserDaoImpl與GreetingRuleDaoImpl。這樣設計就為我們Mock掉UserDao與GreetingRuleDao的實現類創造了條件。

這是我們的設計:


圖4.3 HelloWorld的設計圖


為此,我們編寫了這樣的測試程序:

    	private HelloWorld helloWorld = null;
	private GreetingToUserImpl greetingToUser = null;
	private GreetingAboutTimeImpl greetingAboutTime = null;
	private final static List<GreetingRule> GREETING_RULES = getRules();
	
	/**
	 * @throws java.lang.Exception
	 */
	@Before
	public void setUp() throws Exception {
		helloWorld = new HelloWorld();
		greetingToUser = new GreetingToUserImpl();
		greetingAboutTime = new GreetingAboutTimeImpl();
		helloWorld.setGreetingToUser(greetingToUser);
		helloWorld.setGreetingAboutTime(greetingAboutTime);
	}
	
	/**
	 * @throws java.lang.Exception
	 */
	@After
	public void tearDown() throws Exception {
		helloWorld = null;
		greetingToUser = null;
		greetingAboutTime = null;
	}

	/**
	 * Test method for {@link org...HelloWorld#sayHello(java.util.Date, java.lang.String)}.
	 */
	@Test
	public void testSayHelloInTheMorning() {
		final Date now = DateUtil.createDate(2013, 9, 7, 9, 23, 11);
		final long userId = 2013090701;
		
		UserDao userDao = createMock(UserDao.class);
		GreetingRuleDao greetingRuleDao = createMock(GreetingRuleDao.class);
		expect(userDao.loadUser(userId)).andAnswer(new IAnswer<User>(){
			@Override
			public User answer() throws Throwable {
				User user = new User();
				user.setUserId(userId);
				user.setName("鮑曉妹");
				return user;
			}});
		expect(greetingRuleDao.findAllGreetingRules())
		.andAnswer(new IAnswer<List<GreetingRule>>(){
			@Override
			public List<GreetingRule> answer() throws Throwable {
				return GREETING_RULES;
			}});
		replay(userDao);
		replay(greetingRuleDao);
		
		greetingToUser.setUserDao(userDao);
		greetingAboutTime.setGreetingRuleDao(greetingRuleDao);
		
		String result = helloWorld.sayHello(now, userId);
		Assert.assertEquals("Hi, 鮑曉妹. Good morning!", result);
		verify(userDao);
		verify(greetingRuleDao);
	}
  


這段測試程序比較長,但其它部分都是打醬油的,核心是那個testSayHelloInTheMorning()用例,即問候早上好這個用例。userDao與greetingRuleDao是兩個接口,我們在實例化它們的時候,并沒有去創建它們的實現類,而是用Mock的方式進行創建:

    	UserDao userDao = createMock(UserDao.class);
	GreetingRuleDao greetingRuleDao = createMock(GreetingRuleDao.class);
  


隨后我們開始定義它們的行為loadUser()與getAllGreetingRules()。在這個測試用例中,我們并不關心它們是怎樣去數據庫里查詢數據并返回的,我們只關心它們是否得到應該得到的參數,并要求它們按照規定返回一個結果:

    	final long userId = 2013090701;
	expect(userDao.loadUser(userId)).andAnswer(new IAnswer<User>(){
			@Override
			public User answer() throws Throwable {
				User user = new User();
				user.setUserId(userId);
				user.setName("鮑曉妹");
				return user;
			}});
  



我們希望被測程序在執行的時候調用了userDao.loadUser(userId),并且調用時傳入的參數userId = 2013090701。如果測試過程中傳入的參數是這個值,這一項檢查點可以通過,否則不能通過。隨后我們希望該函數返回“鮑曉妹”這個用戶對象。通過Mock程序,我們完全將數據庫訪問的過程剝離在自動化測試之外,而只是驗證它的輸入參數,并指定測試所需的返回結果。也就是說數據訪問過程被Mock掉,而大大降低了測試難度。

如果UserDao與GreetingRuleDao的Mock程序不能得到規定的參數時,測試就不能通過,這就是說傳遞給Mock程序的參數也成為了測試程序要驗證的一個輸出。隨后,Mock程序返回規定值,該規定值則成為了被測程序的一個輸入。最后,被測程序根據這個輸入返回結果,為測試程序所驗證,測試結束(如圖4.4所示)。


圖4.4 HelloWorld的自動化測試


圖中的BUS層才是我們大量編碼,應當自動化測試的部分。既然是測試就是驗證怎樣的輸入,應當得到怎樣的輸出。Web層向BUS層發出的請求,即調用BUS層某個類的方法,就是測試用例中的一個輸入,執行完該方法后的返回值就是測試用例的一個輸出。但是,這對輸入輸出并不是該測試用例的全部。這里經過BUS層處理以后,經過一系列的邏輯判斷和數據操作,隨后會去調用DAO層進行數據訪問操作。調用DAO層時所傳遞的參數,就是測試用例的另一個輸出。圖中,從DAO層的輸入,到它的輸出,這段數據庫訪問的過程被Mock程序Mock掉了,因為它不在這個用例的測試范圍。然后DAO層返回給BUS層一個結果,該結果就是測試用例的另一個輸入。接著BUS層會再次對這個返回結果進行處理,最后返回給Web層最終的結果。這就是采用Mock方式進行自動化測試的一個完整流程。

采用自動化測試,測試程序將不再驗證后臺的數據庫是否正確,同時也不再驗證前臺的Web應用及其前端設備是否正確。在該例中,系統的真正目的是要在前臺顯示對用戶的問候,因此將會有一個Action或Servlet調用HelloWorld:

    	Date now = DateUtil.getNow();
	String user = SessionUtil.getCurrentUser(session);
	HelloWorld helloWorld = new HelloWorld();
	String greeting = helloWorld.sayHello(now, user);
	request.setAttribute(“greeting”, greeting);
  


然而,這些程序都不適合自動化測試而應采用手工測試。回顧HelloWorld自動化測試建立的過程我們不難發現,它在設計之初就實現了業務邏輯與Web應用、與數據訪問的分離,所以它可以輕易的建立自動化測試。但是,不幸的是,我們大多數的遺留系統在設計之初都沒有考慮到這些。因此,我說,在重構之初首先建立自動化測試機制是不現實的,我們只能采用手工測試結合QTP的方式。只有當我們通過重構,使系統架構滿足自動化測試的條件之后,自動化測試才可以開展。

毫無疑問,測試與重構形成了一個“雞生蛋,還是蛋生雞”的怪圈,成為我們實踐系統重構一大攔路虎。本書將在后面詳細討論這個話題(詳見 第十六章 測試的困境),為你破解這個謎團。

大話重構連載首頁: http://fangang.iteye.com/blog/2081995
特別說明:希望網友們在轉載本文時,應當注明作者或出處,以示對作者的尊重,謝謝!

大話重構連載15:采用Mock技術完成測試


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 2021国产精品自产拍在线观看 | 亚洲色图片区 | 精品毛片 | 亚州中文| 免费国产成人高清视频网站 | 全免费午夜一级毛片一级毛 | 精品久久久久久中文 | 欧美日韩无线码免费播放 | 欧美狂猛xxxxx乱大交3 | 综合精品| 色婷婷综合久久久久中文一区二区 | 亚洲一区精品在线 | 久久av一区二区三区 | 超碰97免费观看 | 日本jizzz| 国产成人精品久久二区二区91 | 国产一区二区三区免费观看 | 在线一区视频 | 欧美三级在线 | 国产目拍亚洲精品99久久精品 | 成人av播放 | 中文乱码一二三四有限公司 | 国产一区 | www.尤物视频 | 日韩一区不卡 | 国产美女高清片免费观看 | 欧美日韩一区二区高清视 | 一区二区三区高清视频在线观看 | 午夜激情影院 | 欧美精品黄页在线观看大全 | 91高清视频在线免费观看 | 丝袜中文字幕 | 国产做a| 99成人| 欧美一级毛片欧美大尺度一级毛片 | 日本午夜精品一区二区三区电影 | 黄色免费观看 | 久久中文精品 | 久色视频在线观看 | 日本高清乱理伦片中文字幕啊 | 欧美精品网站 |