2013-03-21 7 views
8

申し訳ありませんこれは初心者の質問ですが、コミュニティが私が次のメソッドをスタブしている問題に関して提供できる洞察を本当に感謝します。 GrailsサービスでLocationServiceを持っています。Spockを使ってGrailsドメインクラスのGormメソッドと他のメソッドをスタブする

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

私は、ドメインクラス、要求、それだけでなく、デフォルトのGORMの方法も例えば、いくつかの余分なドメインのメソッドを持っています。以下のcreate()メソッド

@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()) 
    } 

最後に、私はSpock仕様を持っています。私は、デフォルトのGORMメソッドの両方をモックする必要がありますが、テスト中のコードに永続化される有効なオブジェクトを返すために、スタティックないくつかの追加のドメインロジック、例えば静的なcreateメソッドも必要です。

理想的には、私はSpockモックを使用しますが、ピーターNの下のポストによれば、ここでは使用できません。これらは呼び出し元に注入する必要があり、この場合はリクエスト(私はモックしようとしています

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

はまた私は、これがGORMメソッドをモックますが、私はもしわからないよ、などのGrails 2.xの@Mockアノテーションを使用することができます)、LocationServiceで見つける方法でローカル変数として作成されます私は、追加のstatic create()メソッドをRequestクラスからモック/スタブすることができます。

最後に私は、これを使用するためにGroovy StubFor/MockForメソッドを使用しようとしていましたが、これはテストメソッドの呼び出しでこれを使用クロージャー(以下参照)にラップして使用すると信じています。ここで

は、テスト仕様です:

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

しかし、私はテストを実行すると、スタブは、方法は私のリクエストスタブオブジェクトを返す作成しますが、私はsaveメソッドスタブ上の失敗を取得:

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() 

誰かが私がここで間違っていることを指摘してください。また、特別なケースを解決するための最良の方法を提案してください。また、GORMメソッドをドメインクラスのスタブに追加する必要がある場合は、テスト?

は、私はあなたがGORM方法について述べたようにGrailsの@Mockアノテーションを使用することができるはず、その後、手動で静的メソッドを模擬する必要があると考えている

パトリック

答えて

8

、事前にありがとう:

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

@Mockアノテーションを使用すると、Grailsのデフォルトのメソッド(/取得/ダイナミックファインダを保存)モックますが、あなたはマヌする必要があるので、それは、あなたが追加した可能性のある追加のメソッドに何もしません同盟国はそれらを嘲笑する。

+0

ありがとうGrailsGuy。それは私の問題を解決しました。 '@ Mock'を使ってデフォルトのメソッドをモックする方法と、手動で追加のメソッドをオーバーライドする方法との間に少しばたつきがありました。 '@ Mock 'を使うと私に前者が与えられたが後者は与えられなかった。 StubForを使って私に後者を与えましたが、前者は与えませんでした。しかし、彼らは一緒に働くようには見えませんでした。しかし、前者に '@ Mock'を使い、後者を得るためにmetaClassを修正することは、問題を完全に解決します。どうもありがとう。 – Paddy

+1

@Paddy問題はありません、うれしく思っています! – Igor

+1

@Igorは、それは私のために働いていたものです「Request.metaClass.static.create ...」である必要があります! – Champ

関連する問題