Spock 模拟私有变量

Eri*_*ari 7 groovy mockito spock

我想知道如何使用 Groovy/Spock 模拟类中的某些私有变量。假设我们有这样的代码:

public class Car {
    private Engine engine;

    public void drive(){
        System.out.println("test");
        if (engine.isState()) {
            // Do something
        } else {
           // Do something
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在 Mockito 中我可以写:

@Mock
private Engine engine;

@InjectMocks
private Car car = new Car();

@Test
public void drive() {
    when(engine.isState()).thenReturn(true);
    car.drive();
}
Run Code Online (Sandbox Code Playgroud)

但我不知道如何在 Spock 中做同样的事情。@InjectMocksSpock 中相当于什么?

kri*_*aex 4

这更像是一个 Groovy 问题,而不是 Spock 问题。在 Groovy 中,您只需调用命名私有成员的构造函数即可注入它。但这很丑陋,您应该像蒂姆·耶茨(Tim Yates)所说的那样,通过依赖注入重构可测试性。但就其价值而言,您可以(但不应该)这样做:

package de.scrum_master.stackoverflow;

public class Engine {
  private boolean state;

  public boolean isState() {
    return state;
  }
}
Run Code Online (Sandbox Code Playgroud)
package de.scrum_master.stackoverflow;

public class Car {
  private Engine engine;

  public void drive(){
    System.out.println("driving");
    if(engine.isState()) {
      System.out.println("true state");
    } else {
      System.out.println("false state");
    }
  }
}
Run Code Online (Sandbox Code Playgroud)
package de.scrum_master.stackoverflow

import spock.lang.Specification

class CarTest extends Specification {
  def "Default engine state"() {
    given:
    def engine = Mock(Engine)
    def car = new Car(engine: engine)

    when:
    car.drive()

    then:
    true
  }

  def "Changed engine state"() {
    given:
    def engine = Mock(Engine) {
      isState() >> true
    }
    def car = new Car(engine: engine)

    when:
    car.drive()

    then:
    true
  }
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,then: true是因为你的方法返回void,我不知道你还想检查哪些其他内容。

测试是绿色的,控制台日志如下所示:

driving
false state
driving
true state
Run Code Online (Sandbox Code Playgroud)