日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Groovy/Spock 测试导论

發布時間:2025/3/14 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Groovy/Spock 测试导论 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

測試對于軟件開發者而言至關重要,不過總會有人說:“寫代碼是我的事,測試那是QA的工作”,這樣的想法真是弱爆了,因為大量的業界實踐已經證明測試驅動編碼可以有效地幫助開發者提升代碼質量。

大多數遵循TDD的Java開發者均會使用mockito或powermock,但mockito和powermock均包含了許多樣本代碼,導致測試代碼變得冗長而難以維護。在測試中引入Groovy/Spock后,我完全被它們吸引,并轉向使用Groovy/Spock來替代原有的測試框架。

下面將圍繞一個簡單例子來講解Groovy/Spock,例子中將包含一個service類,負責處理domain對象,以及一個數據訪問層。
首先是domain類:

public class User {private int id; private String name; private int age; // Accessors omitted }

接下來是DAO接口:

public interface UserDao {public User get(int id); }

最后是service類:

public class UserService {private UserDao userDao;public UserService(UserDao userDao) { this.userDao = userDao; } public User findUser(int id){ return null; } }

采用Groovy/Spock針對UserService編寫測試

class UserServiceTest extends Specification { UserService service UserDao dao = Mock(UserDao) def setup(){ service = new UserService(dao) } def "it gets a user by id"(){ given: def id = 1 when: def result = service.findUser(id) then: 1 * dao.get(id) >> new User(id:id, name:"James", age:27) result.id == 1 result.name == "James" result.age == 27 } }

上述測試代碼中,首先我們使用了groovy,這是一種非常類似Java的語言,但是它的語法更加輕,例如它不用像Java語言那樣,在每句結尾加上分號;它也不需要使用public修飾符,因為public是默認的。上述測試類繼承自spock.lang.Specification,這是Spock基類,繼承該基類后就可以使用given,when,then等代碼塊。

在Spock中創建mock對象非常容易,只需要使用Mock(Class)這樣的語句即可。如上所述,mock后的DAO對象被傳入userService中。Setup方法會在每個測試方法運行前被執行。

Groovy的一個顯著特點是可以使用字符串文本來命名方法,將這個特點應用在測試方法上就能使得測試方法可以更加容易被閱讀和理解,如上述代碼所示。

Given, when, then

Spock是一個BDD測試框架,因此對于Spock中涉及的given,when,then樣式最簡單的理解就是:
Given?給定一些條件,When?當執行一些操作時,Then?期望得到某個結果。

如上述測試方法中Given,給定id=1,即測試的變量;而在When中則是被測試方法,如在上述代碼中調用findUser();Then中則是斷言,即檢查被測試方法的輸出結果。

上述Then中的第一句語句雖然看上去可怕,但實際上卻非常容易理解:

1 * dao.get(id) >> new User(id:id, name:"James", age:27)

該行表示了對于mock對象dao的期望值,即期望調用dao.get()方法1次,而“>>”是spock的特色,表示“then return”含義。因此該句翻譯過來的意思是:期望調用1次dao.get()方法,當執行該方法后,請返回一個新的User對象。此外在構造方法中使用具名參數也是groovy的另一特點。Then中剩余的代碼對result對象進行檢查。

由此測試代碼驅動產生的產品代碼非常簡單,如下所示:

public class UserService {private UserDao userDao;public UserService(UserDao userDao) { this.userDao = userDao; } public User findUser(int id){ return userDao.get(id); } }

接下來實現創建用戶功能,在UserService中添加如下代碼:

public void createUser(User user){ // check name // if exists, throw exception // if !exists, create user }

在UserDao中添加如下方法:

public User findByName(String name); public void createUser(User user);

相應的測試方法如下:

def "it saves a new user"(){ given: def user = new User(id: 1, name: 'James', age:27) when: service.createUser(user) then: 1 * dao.findByName(user.name) >> null then: 1 * dao.createUser(user) }

在上述代碼中出現了兩處Then,這是因為當所有斷言放在一個then塊中,Spock會認為這些斷言是同時發生的。如果期望斷言按順序執行,則需要將斷言分割到多個then塊中,spock會按順序執行斷言。如上述所示,首先需要判斷用戶是否存在,然后再去創建用戶。產品代碼實現如下:

public void createUser(User user){ User existing = userDao.findByName(user.getName()); if(existing == null){ userDao.createUser(user); } }

上述代碼針對用戶不存在場景,而對于用戶存在的場景,測試代碼如下:

def "it fails to create a user because one already exists with that name"(){ given: def user = new User(id: 1, name: 'James', age:27) when: service.createUser(user) then: 1 * dao.findByName(user.name) >> user then: 0 * dao.createUser(user) then: def exception = thrown(RuntimeException) exception.message == "User with name ${user.name} already exists!" }

上述代碼當調用findByName時,返回一個存在的用戶,然后不調用createUser(),第三個Then塊捕獲方法拋出的異常。注意groovy擁有一個稱之為GStrings的特征,該特征可以在引用的字符串中插入參數,如${user.name}。相應產品代碼如下:

public void createUser(User user){ User existing = userDao.findByName(user.getName()); if(existing == null){ userDao.createUser(user); } else{ throw new RuntimeException(String.format("User with name %s already exists!", user.getName())); } }

提示

  • 最重要也是最容易被遺忘的提示,閱讀spock文檔!
  • 可以命名spock塊,例如將given命名為“Some variables”,有助于開發者在測試代碼中更加清楚的表達含義
  • 當對mock對象方法調用次數不關心時,可以使用_ * mock.method()
  • 在then塊中可使用下劃線來通配方法及類,例如,0 * mock._ 表示期望mock對象的任何方法都未被調用,或0 *?.?表示期望任何對象的任何方法都未被調用
  • 通常按given,when,then編寫測試,但實際上從when開始編寫測試會更加容易發現測試需要的given和測試的輸出結果(then)
  • expect塊對于測試不需要對mock對象進行斷言的簡單方法更加有效
  • 當對于傳遞給mock對象的參數不關注時,可以使用通配符參數
  • 擁抱groovy閉包Embrace groovy closures! They can be you’re best friend in assertions!
  • 當希望在整個測試類中只運行一次,可以復寫setupSpec和cleanupSpec

結論

測試代碼是為了協助開發者的,而不是起相反作用,groovy在這方面提供了很多快捷方式來幫助開發者寫出更加優雅的測試代碼。完整代碼可參考https://gist.github.com/jameselsey/8096211

思考

翻譯這篇文章是受到了《使用 Groovy 語言替代 JUnit 來為 Java 程序編寫單元測試》和《The Coding Kata: FizzBuzzWhizz in Modern Java》兩篇文章的啟示。除了贊嘆兩篇文章中采用的測試框架的易用,也深深地被groovy所吸引,其作為DSL的特質不論是對于追求編寫更好測試用例的精益開發者還是對于剛入門測試用例的新手開發者來說都是容易掌握和使用的。我們期望測試用例的目標就是能夠作為產品代碼的?living docs,最佳的效果就是完全擺脫編程語言的語法束縛,成為純粹的書寫或口頭表達方式,這樣就能“望文生義”。Groovy在這方面確實對于Java測試用例編寫起到了促進作用,再加上groovy與Java的無縫融合,及自身擁有的語法特性,在團隊中推廣groovy替代傳統Java測試框架的唯一阻力就剩下大多數開發者是否愿意學習一門新的編程語言。

轉載于:https://www.cnblogs.com/xingzc/p/6349809.html

總結

以上是生活随笔為你收集整理的Groovy/Spock 测试导论的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产精品无码午夜福利 | 我们的2018中文免费看 | 欧美精品人妻一区二区 | 91正在播放 | 九草av | 琪琪电影午夜理论片八戒八戒 | 亚洲国产精品一区二区尤物区 | 欧美日韩aa| 青青草综合视频 | 原来神马电影免费高清完整版动漫 | 久久久人妻无码一区二区 | 亚洲激情一区二区 | 超碰人人人人人人 | 国模私拍一区二区三区 | 午夜久久久久久噜噜噜噜 | 亚洲精品国产福利 | 成人动漫在线免费观看 | 色资源av| 午夜黄色网 | 亚洲免费色视频 | 农村末发育av片一区二区 | 草草影院最新地址 | 图片区偷拍区小说区 | 天天操妹子 | 国产精品男女视频 | 97精品自拍 | 久草91| 少妇被又大又粗又爽毛片久久黑人 | 国产浮力影院 | 青青草视频网站 | 日本中文字幕在线视频 | 亚洲一区www| 成年在线观看 | 黑人操亚洲美女 | 久久久亚洲一区二区三区 | 久久不卡免费视频 | 国产3区| 成人免费黄色 | 日韩欧美视频一区二区 | 国产美女精品久久 | 国产专区视频 | 久久综合五月 | 黄a免费网络 | 亚洲在线视频一区 | 日韩精品无码一区二区三区 | 亚洲欧美伊人 | 一区二区三区高清不卡 | 伊人精品视频在线观看 | 天天碰天天碰 | 国产精自产拍久久久久久蜜 | 欧美体内谢she精2性欧美 | 国产一区二区三区免费播放 | 男女污污软件 | 91高清免费 | 射射色 | 黄色片a| 成人免费视频久久 | 自拍99| av国产免费| 青青草一区二区 | 黄网站在线观 | 日韩中字在线 | 91pao| 在线午夜 | 在线看免费av | 美女自拍偷拍 | 波多野结衣久久久久 | 午夜小影院 | 成人gav| av黄色影院 | 日本午夜影视 | 日韩七区 | 日韩黄色免费 | 青草综合| 欧美七区 | 国产午夜激情视频 | 无码aⅴ精品一区二区三区 精品久久在线 | 精品人妻一区二区三区四区在线 | 丝瓜av| 老司机福利av | 成人午夜福利视频 | 在线播放国产精品 | 日本久久久网站 | 欧美日韩另类一区 | 免费看国产片在线观看 | 巨物撞击尤物少妇呻吟 | 精品色综合 | 香蕉国产| 日本中文字幕不卡 | 91禁蘑菇在线看 | 一级黄色免费大片 | 精品久久人人 | 欧美一区免费观看 | 久久精品久久精品 | 成人免费观看视频 | 久久精品国产熟女亚洲AV麻豆 | 久久久久成人精品无码 | 成人精品免费在线观看 | 乱一色一乱一性一视频 |