2013-03-21 28 views
8

Xin lỗi nếu đây là câu hỏi mới nhưng tôi thực sự đánh giá cao bất kỳ thông tin chi tiết nào mà cộng đồng có thể cung cấp liên quan đến vấn đề tôi đang gặp phải có trong một dịch vụ Grails, LocationService.Sử dụng Spock để phân tích cả Gorm và các phương thức khác trong lớp miền Grails

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

Tôi có một lớp miền, Yêu cầu, cũng như các phương pháp GORM mặc định cũng có một số phương pháp tên miền bổ sung, ví dụ: phương thức create() bên dưới

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

Cuối cùng, tôi có đặc điểm Spock. Tôi cần phải giả lập cả hai phương thức GORM mặc định nhưng cũng có một số sơ khai thêm một số logic miền, ví dụ, một phương thức tạo tĩnh, để trả về một đối tượng hợp lệ được duy trì trong mã đang được kiểm thử. Lý tưởng nhất, tôi sẽ sử dụng mock Spock nhưng tôi không thể sử dụng chúng ở đây theo bài viết dưới đây của Peter N, chúng cần được tiêm vào người gọi và trong trường hợp này là Yêu cầu (mà tôi đang cố gắng để giả lập)), được tạo ra như là một biến địa phương trong xác định vị trí phương pháp trong LocationService:

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

Cũng không phải tôi có thể sử dụng Grails 2.x @Mock chú thích như, mặc dù điều này sẽ thử các phương pháp GORM, tôi không chắc chắn nếu tôi có thể giả lập/stub phương thức create() tĩnh bổ sung từ lớp Request. Do đó, cuối cùng, tôi đã cố gắng sử dụng các phương thức Groovy StubFor/MockFor để làm điều này vì tôi tin rằng các phương thức này sẽ được sử dụng trong cuộc gọi đến phương pháp thử bằng cách gói nó trong một kết thúc sử dụng (như bên dưới).

Dưới đây là spec kiểm tra:

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

Tuy nhiên, khi tôi chạy thử nghiệm, mặc dù stubbed tạo phương thức trả về đối tượng còn sơ khai Yêu cầu của tôi, tôi nhận được một thất bại trên stubbed tiết kiệm phương pháp:

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

Có ai vui lòng chỉ ra những gì tôi đang làm sai ở đây hoặc đề xuất phương pháp tốt nhất để giải quyết trường hợp cụ thể của tôi nếu cần phải thêm phương thức cũng như phương pháp GORM của một lớp miền mà tôi không thể tiêm trực tiếp vào mã kiểm tra?

Cảm ơn bạn trước,

Patrick

Trả lời

8

Tôi tin rằng bạn sẽ có thể sử dụng Grails' @Mock chú thích như bạn đề cập đến cho các phương pháp GORM, và sau đó bạn sẽ cần phải tự thử các phương pháp tĩnh:

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

Khi sử dụng @Mock chú thích, Grails sẽ thử các phương pháp mặc định (lưu/get/Finders động), nhưng nó không làm bất cứ điều gì với bất kỳ phương pháp bổ sung mà bạn có thể bổ sung, vì vậy bạn cần phải manu đồng minh chế nhạo những người đó.

+0

Cảm ơn bạn GrailsGuy. Đó là giải quyết vấn đề của tôi. Tôi đã nhận được vào một chút của một rối giữa sử dụng '@ Mock' để giả lập các phương pháp mặc định và làm thế nào để tự ghi đè lên phương pháp bổ sung. Sử dụng '@ Mock' đã cho tôi cái cũ chứ không phải cái sau. Và bằng cách sử dụng StubFor đã cho tôi sau này nhưng không phải là cựu. Nhưng họ dường như không làm việc chung. Tuy nhiên, bằng cách sử dụng '@ Mock' cho phần trước và sửa đổi metaClass để giải quyết vấn đề này một cách hoàn hảo. Cảm ơn nhiều. – Paddy

+1

@Paddy Không sao, tôi rất vui được giúp đỡ! – Igor

+1

@Igor Nếu nó là "Request.metaClass.static.create ..." Đó là những gì làm việc cho tôi! – Champ