簡體   English   中英

Spock groovy - 如何模擬同一個類中的方法?

[英]Spock groovy - how to mock methods in same class?

如何在測試類中模擬不同類中的私有方法和方法?

class MyClass {
    private final Retriever<ScoreData> retriever;
    private DataStore<Model> dataStore;
    private String gameName;

    public void MyClass(Retriever<ScoreData> retriever, DataStore<Model> dataStore, String gameName) {
        this.retriever = retriever;
        this.dataStore = dataStore;
        this.gameName = gameName;
    }

    public void process(GameHolder<G> games) {
        // Business Logic
        for (Game<G> game : games){
        Integer score = game.getScore();
        Integer playerId = game.getPlayerId();
        Integer finalScore = getScore(game);
        computeScore(score, finalScore);
        }
    }

    private Integer computeScore(int score, int finalScore) {
        // Runs some business logic and returns O3
        return score + finalScore;
    }

    private Integer getScore(Game game) {
        // Runs some business logic and returns O3
        String dbName = game.getDbName();
        DBRetriever ret = new DBRetriever(dbName)
        if (dbName.equals("gameDB"){
            return ret.getFinalScore(dbName);
        }
        return -1;
    }

}

下面是我當前對 Spock 的實現,我不確定如何實現對象的模擬。

@Subject
def obj

def "this is my test"(){
    given:
    Object1 obj1 = Mock(Object1)
    Object2 obj2 = Mock(Object2)
    Object3 obj3 = Mock(Object3)

    def myClassObject = new MyClass(obj1, obj2, obj3)

    when:
    myClassObject.process(new Object4())

    then:
    1 * getScore()
    1 * computeScore()

}

如何模擬 computeScore 和 getScore 函數以及如何為對象 obj1、obj2、obj3 分配初始值?

注意:我只是想在這里測試process()方法。 但是 process 方法正在從內部調用私有方法。 我希望能夠為私有方法返回一個模擬值,而不是執行私有方法。

編輯:Retriever 和 DataStore 是接口,它們各自的實現是 ScoreData 和 Model。

注意:我只是想在這里測試process()方法。 但是 process 方法正在從內部調用私有方法。 我希望能夠為私有方法返回一個模擬值,而不是執行私有方法。

您不應該這樣做,因為MyClass是您正在測試的班級。 如果你存根測試,你就不能用測試覆蓋私有方法中的邏輯。 相反,如果注入的模擬在這些私有方法中使用,您應該確保它們按照您希望的方式運行(通過存根方法)。 不幸的是,您決定不顯示代碼的關鍵部分,即使確切的答案取決於它。 相反,您將它們替換為注釋“一些業務邏輯”,這不是很有幫助,因為您的業務邏輯是您要測試的內容。 你不想把它存起來。


所以請不要做我在這里展示給你的東西,我只是因為你問了才回答。

為了存根方法,它不能是私有的,因為從技術上講,間諜、模擬或存根始終是子類,或者原始和子類不能繼承甚至調用私有方法。 因此,您需要使方法受保護(以便子類可以使用或覆蓋它們)或包作用域。 我推薦前者。

但是您不能使用普通的模擬或存根作為被測類的替代品,因為您只想刪除部分業務邏輯(您有問題的兩個方法),而不是整個邏輯(您想保留process() )。 因此,您需要一個部分模擬。 為此,您可以使用間諜。

虛擬依賴類:

package de.scrum_master.stackoverflow.q60103582;

public class Object1 {}
package de.scrum_master.stackoverflow.q60103582;

public class Object2 {}
package de.scrum_master.stackoverflow.q60103582;

public class Object3 {}
package de.scrum_master.stackoverflow.q60103582;

public class Object4 {}

被測類:

package de.scrum_master.stackoverflow.q60103582;

public class MyClass {
  private Object1 o1;
  private Object2 o2;
  private Object3 o3;

  public MyClass(Object1 o1, Object2 o2, Object3 o3) {
    this.o1 = o1;
    this.o2 = o2;
    this.o3 = o3;
  }

  public void process(Object4 o4) {
    System.out.println("process - business Logic");
    Object2 result = getScore("dummy ID");
    Object3 obj = computeScore(result);
  }

  protected Object3 computeScore(Object2 result) {
    System.out.println("computeScore - business logic");
    return o3;
  }

  protected Object2 getScore(String id) {
    System.out.println("getScore - business logic");
    return o2;
  }
}

斯波克測試:

package de.scrum_master.stackoverflow.q60103582

import spock.lang.Specification

class MyClassTest extends Specification {
  def "check main business logic"(){
    given:
    Object1 obj1 = Mock()
    Object2 obj2 = Mock()
    Object3 obj3 = Mock()

    MyClass myClass = Spy(constructorArgs: [obj1, obj2, obj3])

    when:
    myClass.process(new Object4())

    then:
    1 * myClass.getScore(_) //>> obj2
    1 * myClass.computeScore(_) //>> obj3
  }
}

在這里你可以看到如何檢查間諜的交互。 但請注意, computeScore(_)getScore(_)仍然會被執行,正如您在控制台日志中看到的:

process - business Logic
getScore - business logic
computeScore - business logic

如果取消注釋最后兩行代碼的結尾

    1 * myClass.getScore(_) >> obj2
    1 * myClass.computeScore(_) >> obj3

您實際上將避免完全執行這兩個(受保護的)方法並用存根結果替換它們。 控制台日志將更改為:

process - business Logic

但我要再說一遍:不要這樣做。 相反,請確保您注入的模擬顯示正確的行為,以便您可以實際執行被測類中的方法。 這就是測試的意義,不是嗎?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM