2016-04-11 16 views
5

Trong một số kỹ thuật Spock bất kỳ dòng trong mong đợi: hoặc thì: khối được đánh giá và khẳng định như boolean, trừ khi nó có chữ ký với sự trở lại loại void.Có cách nào để ngăn Geb trả về null từ các phương thức không?

Tôi đã nhận thấy rằng có điều gì đó kỳ lạ xảy ra đối với các phương thức được khai báo là void đối với bất kỳ lớp nào kế thừa từ Navigator (ví dụ: Page hoặc Module lớp).

Hãy nói rằng chúng ta có ví dụ như:

class NavigationSpec extends GebSpec { 

    def 'Collections page has a right header'() { 

     when: 
      to CollectionsPage 

     then: 
      hasHeaderText('Collections') 
    } 
} 

Phương pháp hasHeaderText() được định nghĩa trong CollectionsPage lớp như sau:

class CollectionsPage extends Page { 

    static url = 'movies/collections' 

    void hasHeaderText(String expectedText) { 
     assert true 
    } 
} 

Mở mục đích Tôi chỉ khẳng định true đằng kia nên nó sẽ không bao giờ Thất bại. Mặc dù nó không thành công với một lỗi:

Condition not satisfied: 

hasHeaderText('Collections') 
| 
null 

Làm thế nào và tại sao một kết quả gọi void phương pháp được đánh giá là null?

Tôi biết cách 'khắc phục sự cố'. Đủ để khai báo kiểu trả về của phương thức là boolean và trả lại true. Điều này là xấu mặc dù như sau tất cả các khẳng định khác không cần thiết return true phải được thêm vào như:

boolean hasHeaderText(String expectedText) { 
    assert header.text() == expectedText 
    return true 
} 

Điều này chỉ gây ra tiếng ồn. Có cách nào để ngăn Geb trả lại null từ các phương thức void không?

tôi, tất nhiên, nhận thức được rằng trường hợp cụ thể này có thể đi như:

boolean hasHeaderText(String expectedText) { 
    header.text() == expectedText` 
} 

này không giải thích kỳ quặc của mất loại void trở lại, chưa kể chúng ta mất đi ý nghĩa thông báo lỗi assert với cách tiếp cận như vậy.

Trả lời

4

Đó là một phần của ngôn ngữ Groovy mà mọi phương thức đều trả về một giá trị. Điều này cho phép bất kỳ phương thức nào được sử dụng trong các biểu thức hoặc như lambdas.

Tất cả các phương pháp được khai báo void trả lại null.

Nếu bạn không rõ ràng có bất kỳ câu lệnh trả về nào, kết quả của biểu thức cuối cùng trong phương thức của bạn được trả về.

Bạn có thể ghé qua bytecode ... ngay cả khi bạn khai báo một kiểu trả về, bạn không thực sự cần phải trả lại bất cứ điều gì như Groovy sẽ, theo mặc định, trả về null:

// returns null 
String callMe() { } 

static void main(args) { 
    def x = callMe() 
    assert x == null 
    println "OK!" 
} 

Vì Spock sẽ khẳng định mọi thứ trong khối then không phải là nhiệm vụ đơn giản, bạn cần tránh thực hiện bất kỳ điều gì khác ngoài xác nhận boolean trong khối then. Thậm chí chỉ định một biến, dù được cho phép, nên tránh ... Thật khó để giữ cho các bài kiểm tra rõ ràng và rõ ràng, và bằng cách tôn trọng những hướng dẫn này sẽ thực sự làm việc cho bạn trong thời gian dài, không chống lại bạn.

Vì vậy, cách chính xác để viết khẳng định bạn muốn là làm cho phương pháp của bạn trả về một boolean:

boolean hasHeaderText(String expectedText) { 
    header.text() == expectedText 
} 

Và sử dụng nó trong các then khối:

then: 'The header has the expected text #expectedText' 
hasHeaderText expectedText 

Trông khá tốt nếu bạn hỏi tôi.

EDIT

tôi đã nhận thấy rằng Groovy/Spock thực sự sẽ không khẳng định kết quả của một bình thường trống phương pháp thậm chí trong khối then ... Có gì lẽ xảy ra ở đây là bạn không có phương pháp trống bình thường, bạn dường như đang gọi phương thức động CollectionsPage (tôi đoán đó là phép thuật của Geb), có nghĩa là, Biến thể AST Spock không có cơ hội để kiểm tra chữ ký của phương pháp bạn đang gọi, vì vậy nó chính xác giả định nó phải khẳng định kết quả. .. ít nhất đó là những gì nó trông giống như.

+0

Cảm ơn câu trả lời của bạn. Tôi nhận thức được những điều bạn đã viết, đặc biệt là phần trong ghi chú 'chỉnh sửa'. Thật vậy, phương pháp void không nên được đánh giá như khẳng định trong khối sau đó của spock. Phương thức của trang được khai báo theo cách thông thường, nhưng đó cũng là giả thiết của tôi, rằng Geb thực hiện một số phép thuật AST với nó và do đó phá vỡ hợp đồng. Sử dụng các boolean với 'expectedText' bên ngoài phương thức là xa những gì tôi muốn đạt được. Điện xác nhận các thông báo thất bại phức tạp bị mất (suy nghĩ về việc so sánh hai bản đồ ví dụ) và văn bản phải được lặp lại mỗi khi phương pháp được sử dụng (DRY). Tôi coi đây là lỗi Geb – topr

3

@Renato là chính xác trong phần chỉnh sửa phản hồi của mình - cuộc gọi của bạn đến một phương thức trống được Spock xác nhận vì đó là cuộc gọi năng động và Spock không thể nhận ra rằng bạn đang gọi phương thức trống và háo hức khẳng định cuộc gọi. Nếu bạn đã thay đổi mã của mình thành:

class NavigationSpec extends GebSpec { 

    def 'Collections page has a right header'() { 
     when: 
      CollectionsPage collectionsPage = to CollectionsPage 

     then: 
      collectionsPage.hasHeaderText('Collections') 
    } 

} 

thì nó sẽ không được xác nhận.

+0

Cảm ơn câu trả lời. Tôi đã khá chắc chắn rằng điều này là do một số tính năng động của cuộc gọi. Oddly tôi đã không bắt nó hoạt động tốt nếu được gọi trực tiếp trên đối tượng sở hữu. Nhân tiện, tôi sẽ chấp nhận câu trả lời nào bây giờ? @Renato là lần đầu tiên trong khi bạn cung cấp thêm chi tiết :) – topr

+1

Có lẽ @Renato xứng đáng được chấp nhận vì phản hồi của anh ấy là câu trả lời đúng đầu tiên. :) – erdi

+0

Bạn quá khiêm tốn. Phản ứng @Renato chỉ là một xác nhận chung của các giả định của riêng tôi rằng đó là 'một số phép thuật động' nhưng không có bất kỳ chi tiết nào được cung cấp về những gì đang xảy ra cũng như một giải pháp. Vì vậy, tôi chấp nhận của bạn. Tôi hy vọng anh ta không quan tâm ... – topr

Các vấn đề liên quan