2013-03-21 14 views
8

Sorry, wenn dies eine neue Frage ist, aber ich würde wirklich alle Einsichten, die die Community in Bezug auf ein Problem mit der folgenden Methode Stubbing bieten könnte, die ich in einem Grails-Dienst, LocationService.Mit Spock, um beide Gorm und andere Methoden in einer Grails-Domain-Klasse stumpf

Location locate(String target, String locator, Application app, boolean sync = true) { 
    if (!target) throw new IllegalArgumentException("Illegal value for msid: " + target) 
    def locRequest = Request.create(target, Type.LOCATE) 
    if (!locRequest.save()) { 
      return Location.error(target, "Error persisting location request") 
    } 
    locationSource.locateTarget(target, locator, app, sync) 
} 

Ich habe eine Domain-Klasse, anfordern, dass sowie der Standard GORM Methoden auch einige zusätzliche Domains Methoden haben, zum Beispiel. Die Create() Methode unter

@EqualsAndHashCode 
class Request { 

    String reference 
    String msid 
    Type type 
    Status status 
    Destination destination 
    DateTime dateCreated 
    DateTime dateCompleted 

    static create(String msid, Type type, Destination destination = Destination.DEFAULT) { 
      new Request(reference: reference(type), type: type, status: Status.INITIATED, dateCreated: new DateTime()) 
    } 

Schließlich habe ich eine Spock-Spezifikation. Ich muss sowohl die Standard-GORM-Methoden als auch einige zusätzliche Domänenlogiken, zB eine statische create-Methode, vortäuschen, um ein gültiges Objekt zurückzugeben, das im getesteten Code beibehalten werden soll.

Im Idealfall würde ich Spock Mocks verwenden, aber ich kann sie hier nicht verwenden, wie nach dem Post unten von Peter N, sie müssen in den Anrufer und in diesem Fall die Anfrage (die ich versuche zu verspotten) injiziert werden), wird als lokale Variable in der Methode finden in LocationService erstellt:

https://groups.google.com/forum/?fromgroups=#!topic/spockframework/JemiKvUiBdo

Ebenso wenig kann ich die Grails 2.x @Mock Annotation verwenden, obwohl dies die GORM Methoden verspotten, ich bin nicht sicher, ob Ich kann die zusätzliche statische create() -Methode aus der Request-Klasse nachahmen/stubben.

Daher habe ich schließlich versucht, die Groovy StubFor/MockFor-Methoden zu verwenden, da ich glaube, dass diese in den Aufruf der Testmethode verwendet werden, indem es in eine Verwendung schließen (wie unten). Hier

ist der Test-Spezifikation:

@TestFor(LocationService) 
// @Mock(Request) 
class LocationServiceSpec extends Specification { 

    @Shared app = "TEST_APP" 
    @Shared target = "123" 
    @Shared locator = "999" 

    def locationService = new LocationService() 
    LocationSource locationSource = Mock() 


    def "locating a valid target should default to locating a target synchronously"() { 
     given: 
      def stub = new StubFor(Request) 
      stub.demand.create { target, type -> new Request(msid: target, type: type) } 
      stub.demand.save { true } 
      1 * locationSource.locateTarget(target, locator, app, SYNC) >> { Location.create(target, point, cellId, lac) } 
      def location 
     when: 
      stub.use { 
       location = locationService.locate(target, locator, app) 
      } 
     then: 
      location 
} 

Allerdings, wenn ich den Test ausführen, obwohl die stubbed create-Methode zurückgibt meine Anfrage Stub-Objekt, erhalte ich einen Fehler auf der Stub Speichermethode:

groovy.lang.MissingMethodException: No signature of method:  com.domain.Request.save() is applicable for argument types:() values: [] 
Possible solutions: save(), save(boolean), save(java.util.Map), wait(), last(), any() 

Könnte jemand bitte darauf hinweisen, was ich hier falsch mache oder den besten Ansatz vorschlagen, um meinen speziellen Fall zu lösen, wenn ich zusätzliche Methoden sowie GORM-Methoden einer Domänenklasse, die ich nicht direkt in den Code unter injizieren kann Prüfung?

Vielen Dank im Voraus,

Patrick

Antwort

8

Ich glaube, sollten Sie in der Lage sein zu verwenden Grails' @Mock Anmerkung, wie Sie für die GORM Methoden erwähnt, und dann werden Sie manuell die statischen Methoden verspotten müssen:

@TestFor(LocationService) 
@Mock(Request)// This will mock the GORM methods, as you suggested 
class LocationServiceSpec extends Specification { 
... 
    void setup() { 
     Request.metaClass.static.create = { String msid, Type type, Destination destination = Destination.DEFAULT -> 
      //Some logic here 
     } 
    } 
... 

Bei Verwendung der @Mock Anmerkung, Grails werden die Standardmethoden verspotten (Speicher/get/dynamischen Finders), aber es tut nichts, um zusätzliche Methoden, die Sie haben hinzugefügt, so dass Sie manu müssen Verbünde diese Leute.

+0

Danke GrailsGuy. Das hat mein Problem gelöst. Ich geriet zwischen der Verwendung von '@ Mock' in ein kleines Gewirr, um die Standardmethoden zu überspielen und zusätzliche Methoden manuell zu überschreiben. Die Verwendung von '@ Mock' gab mir das erste, aber nicht das letzte. Und die Verwendung von StubFor gab mir das letztere, aber nicht das erstere. Aber sie schienen nicht zusammen zu arbeiten. Die Verwendung von '@ Mock' für die erste und das Ändern der metaClass, um die letztere zu erhalten, löst das Problem perfekt. Danke vielmals. – Paddy

+1

@Paddy Kein Problem, ich kann Ihnen helfen! – Igor

+1

@Igor Sollte es "Request.metaClass.static.create ..." sein Das hat bei mir funktioniert! – Champ