使用Spock 單元測試

一、什麼是Spock

Spock 是一個測試框架,甚至可以說是一門語言他是基於Groovy開發的。它的語法完全遵循 BDD(行爲驅動開發) 風格的結構。它是基於 Junit test runner 上開發但是又跟 Junit 完成不一樣,同時集成了像 Jmock、Mockito 等語法表達風格於一體,使得它很簡潔有很高的可讀性。

 

 

 

 

二、Spock 優缺點

  •   語法清晰簡單並且有很高的可讀性

  •   不好的就是需要學習下Groovy 的語法,對Maven的配置不是很友好。但是在Gradle 中可以很好的支持

  

三、如何使用Spock

Maven 的配置

 

 

 

 

 

 

  •   Gmavenplus-plugin 插件可以讓你的測試代碼支持 Groovy 語法
  •   Surefire 插件 測試時只執行帶有 Spec後綴的代碼,這個必須是*Spec.java 而不是 groovy
  •   spock-core 就是 spock 的核心包
  •   byte-buddy 用來做動態代理,如果你需要測試的代碼沒有實現接口。spock 無法幫你mock,當然你也可以用 cliglib 代替

 

聲明類

/**
 *
 * @author: serio.shi(苦蔘)
 * @create 2020/08/05 17:22
 * */
public class User {

    private int id;
    private String name;
    private int age;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
View Code

 

Dao 類

interface UserDao {
    public User get(int id);
    public User findByName(String name);
    public void createUser(User user);
}
View Code

 

UserService 類

/**
 *
 * @author: serio.shi(苦蔘)
 * @create 2020/08/05 17:23
 * */
public class UserService {

    private UserDao userDao;

    public UserService(UserDao userDao) {
        this.userDao = userDao;
    }

    public User findUser(int id){
        return userDao.get(id);
    }

    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()));
        }
    }
}
View Code

 

測試 service的findUser 方法 mock dao的get 方法返回一個固定 user

 

是的你沒有看錯,它的方法名就是一個字符串(它有什麼好處後面再講)。它的語法很簡單 given:、when:、then:、

setup 是它的元方法在測試用例執行前調用類似於 @before

  •  given 需要的一些變量參數
  •  when 就是需要測試的方法
  •  then 就是期待的結果

 

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

表示 dao.get(id) 方法將會被調用一次,並且讓他返回 new User(id:id, name:"James", age:27) 對象。並且期待它的結果是 result.id == 1、result.name == "James"、result.age == 27

 

在運行測試後

 

 

 

 

從圖中我們可以看到,我們定義的方法名被打印出來。我們可以很方便的看到我們想要測試的內容成功了。

 

如果驗證沒有通過 Spock 將通過圖表的方式告訴你哪裏出問題,並且它會幫你把兩個值的打印出來幫你做對比(經常有小夥伴寫測試用例的時候把值打印出來用肉眼來識別錯誤)。我們把期待的id改爲12再來試下。

 

 

 

 

 

 

  我們可以看到 Spock 提示你測試用例失敗了,你的id 是1而期待的是12,當你點擊 <Click to see difference> 的時候將會彈出一個框幫你做數據對比。簡直是開發神器啊有木有!!!

 

Spock 還有一個神奇的參數化測試,類似於表格的形式填入參數和期待的結果

 

我們先在UserService類中加上以下代碼:

Map datatable = [1:"jerry", 2:"tom", 3:"tommy", 4:"jack"]
public String getUser(int id){
    return datatable.get(id)
}
View Code

 

添加測試用例:

def "spock parameterized test demo"(){
    expect:
    service.getUser(id) == name
where: "some id with name"
    id || name
    1  || "jerry"
    2  || "tom"
    3  || "tommy"
    4  || "jack"
}

 

可以看到我們可以以更清晰的方式把入參跟結果描述出來,運行結果:

 

 

 

當前它還有很多的姿勢待我們去解鎖,本文只舉例了簡單的案例。

更多詳情點擊:http://spockframework.org/spock/docs/1.3/all_in_one.html#_introduction

 

四、小結

Spock 有着依賴少、運行快、語法簡單、代碼清晰等特點、本文只做簡單的舉例用於學習和記錄

 

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