Erii Asari
Erii Asari

Reputation: 335

Spock mock private variable

I'm wondering how I can mock some private variable in a class with Groovy/Spock. Let's say we have this code:

public class Car {
    private Engine engine;

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

In Mockito I can write:

@Mock
private Engine engine;

@InjectMocks
private Car car = new Car();

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

But I don't know how to do the same in Spock. What is the equivalent of @InjectMocks in Spock?

Upvotes: 7

Views: 14088

Answers (2)

Michael
Michael

Reputation: 2683

I'd suggest to put the Engine into the car when it is constructed:

public class Car {
    private final Engine engine;

    public Car(final Engine engine) {
        this.engine = engine
    }

    // ...
}

Then you can just mock the engine like this using JUnit as in your example:

@Mock
private Engine engine;

private Car car = new Car(engine);

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

Or using Spock:

private Engine engine = Mock();

private Car car = new Car(engine);

def "test drive"() {
    given:
    engine.isState() >> true

    expect:
    car.drive();
}

Upvotes: 0

kriegaex
kriegaex

Reputation: 67317

This is more a Groovy than a Spock question. In Groovy you can just call a constructor naming the private member and thus inject it. But this is ugly, you should rather refactor for testability via dependency injection as Tim Yates already said. But for what it is worth, here is how you can (but shouldn't) do it:

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
  }
}

BTW, then: true is because your method returns void and I don't know which other things you want to check.

The test is green and the console log looks like this:

driving
false state
driving
true state

Upvotes: 4

Related Questions