【问题标题】:Spock mock private variableSpock 模拟私有变量
【发布时间】:2018-08-24 14:35:56
【问题描述】:

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

public class Car {
    private Engine engine;

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

在 Mockito 中我可以写:

@Mock
private Engine engine;

@InjectMocks
private Car car = new Car();

@Test
public void drive() {
    when(engine.isState()).thenReturn(true);
    car.drive();
}

但我不知道如何在 Spock 中做同样的事情。 Spock 中的@InjectMocks 是什么?

【问题讨论】:

  • 引擎在你测试的类中是如何设置的?
  • @tim_yates 它被设置在一些被init方法调用的私有方法中。
  • 您可能希望将其传递给构造函数,以使该类更易于测试

标签: groovy mockito spock


【解决方案1】:

这更像是一个 Groovy 而非 Spock 的问题。在 Groovy 中,您可以只调用一个命名私有成员的构造函数并注入它。但这很难看,您应该通过依赖注入重构可测试性,正如 Tim Yates 已经说过的那样。但就其价值而言,您可以(但不应该)这样做:

package de.scrum_master.stackoverflow;

public class Engine {
  private boolean state;

  public boolean isState() {
    return state;
  }
}
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");
    }
  }
}
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
  }
}

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

测试为绿色,控制台日志如下:

driving
false state
driving
true state

【讨论】:

    【解决方案2】:

    我建议在构建时将Engine放入汽车中:

    public class Car {
        private final Engine engine;
    
        public Car(final Engine engine) {
            this.engine = engine
        }
    
        // ...
    }
    

    然后你可以像在你的例子中那样使用 JUnit 模拟引擎:

    @Mock
    private Engine engine;
    
    private Car car = new Car(engine);
    
    @Test
    public void drive() {
        when(engine.isState()).thenReturn(true);
        car.drive();
    }
    

    或者使用 Spock:

    private Engine engine = Mock();
    
    private Car car = new Car(engine);
    
    def "test drive"() {
        given:
        engine.isState() >> true
    
        expect:
        car.drive();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-09-25
      • 1970-01-01
      • 1970-01-01
      • 2020-02-23
      • 2011-03-18
      • 1970-01-01
      相关资源
      最近更新 更多