2014-03-06 5 views
20

Ich habe Mühe, etwas über Spock-Interaktionen in einem Groovy-Komponententest zu verstehen.Spock: Kann eine in setup() definierte Interaktion in einem Testfall ersetzt werden?

Ich habe folgende Typen:

public interface Bar { 
    public String getMessage(); 
} 

public class Foo { 
    private Bar bar; 
    public void setBar(Bar bar) { 
    this.bar = bar; 
    } 
    public String getMessage() { 
    return bar.getMessage(); 
    } 
} 

und ich schrieb dann den folgenden Groovy/Spock-Test:

class FooSpec extends Specification { 

    private Bar bar; 
    private Foo foo; 

    def setup() { 
    bar = Mock(Bar) { getMessage() >> "hello" } 
    foo = new Foo() 
    foo.bar = bar 
    } 

    def "say hello"() { 
    expect: 
    foo.message.equals("hello") 
    } 

    def "say goodbye"() { 
    setup: 
    bar.getMessage() >> "goodbye" 

    expect: 
    foo.message.equals("goodbye") 
    } 
} 

Der Code ein Mock Bar Instanz im Setup erstellt, initialisiert Bar.getMessage() zurückzukehren hello und weist dies einer neuen Foo Instanz zu. Der erste Test bestätigt, dass foo.getMessage() gleich hello ist.

Der zweite Test versucht, den bar Schein so zu ändern, dass es getMessage Methode goodbye zurückgibt. Wir erwarten dann, dass foo.getMessage() (die an bar.getMessage() delegiert) dann goodbye zurückgeben. Allerdings schlägt der Test fehl, wie folgt:

FooSpec: Abschied nehmen: 26 Bedingung nicht erfüllt

weil foo.message noch gleich hello ist.

Ich habe auch versucht die folgenden:

def "say goodbye"() { 
    when: 
    bar.getMessage() >> "goodbye" 

    then: 
    foo.message.equals("goodbye") 
} 

und:

def "say goodbye"() { 
    when: 
    no_op() 

    then: 
    bar.getMessage() >> "goodbye" 
    foo.message.equals("goodbye") 
} 

Aber beide scheiterte mit dem gleichen hallo Nachricht nicht gleich verabschieden.

Ich denke wahrscheinlich immer noch im Mockito-Modus und nehme an, dass eine Interaktion dem Ausdruck when(...).thenReturn(...) entspricht und dass spätere Interaktionen frühere Interaktionen überschreiben würden.

Gibt es einen einfachen Weg mit Spock, um eine Interaktion in einer setup Methode zu deklarieren, dann überschreiben diese Interaktion in einem Testfall? Oder muss ich die setup() Methode entfernen und grundsätzlich einen setup: Block zu jedem Testfall hinzufügen?

Antwort

19

Das ist eine schwierige Frage. Wie in der docs angegeben, haben in einem then-Block deklarierte Interaktionen Vorrang vor den zuvor deklarierten Interaktionen. Die in einem then-Block deklarierten Interaktionen sind jedoch auf den vorherigen when-Block beschränkt. (Auf diese Weise können mehrere when-dann-Paare haben.) Damit Ihr letzter Versuch nicht funktioniert, aber der folgende Wille:

def setup() { 
    bar.message >> "hello" 
} 

def "say goodbye"() { 
    when: 
    def msg = foo.message 

    then: 
    bar.message >> "goodbye" 
    msg == "goodbye" 
} 

Ich bin damit einverstanden, dass es für Interaktionen wäre gut in Testmethoden erklärt immer Wechselwirkungen außer Kraft setzen in Setup-Methoden deklariert. Eine gute Alternative zum Überschreiben von Interaktionen ist jedoch, dass jede Testmethode eine Hilfsmethode aufruft, die die erwarteten Interaktionen für diese Testmethode einrichtet.

+0

Danke für den Kommentar.Ich werde auf eine 'setup()' Methode verzichten und meine Testmethoden ändern, um ihren Status direkt zu initialisieren (dies wird auch durch die Tatsache motiviert, dass ich oft einen 'wo:' Block in meinen Testmethoden verwende und gefunden habe Meine Überraschung, dass die 'setup()' Methode nach dem 'where:' Block aufgerufen wurde. Ich denke * Ich kann dein Beispiel oben verstehen, aber es ist nicht intuitiv (es sieht immer noch wie Setup-Code im 'then:' Block für mich aus). –

+0

@PeterNiederwieser, welche Spock Version hast du in diesem Beispiel benutzt? Wir haben dies und viele andere Variationen mit Spock 1.0 versucht, aber es hat nicht funktioniert. – falsarella