2014-12-02 88 views
1

我是Grails的新手,希望對使用@Validateable@BindUsing的命令類進行單元測試。像往常一樣,Grails文檔沒有關於它的信息。有什麼建議麼?如何使用@Validateable和@BindUsing單元測試Grails命令對象

當我在它的時候,我該如何測試相應的控制器?

@Validateable 
@ToString 
class SearchMovieRipCommand { 

    MovieRipSearchService movieRipSearchService 

    @BindUsing({ 
     obj, source -> source['fieldName']?.trim() 
    }) 
    String fieldName 

    // more fields, omitted for brevity 

    Collection<MovieRip> search() { 
     log.debug("fieldName: ${fieldName}, fieldValue: ${fieldValue}, max: ${max}.") 

     movieRipSearchService.search(fieldName, fieldValue, max) 
    } 
} 

class MovieRipController { 

    def show(final SearchMovieRipCommand cmd) { 
     respond(cmd.search()) 
    } 
} 
+0

查找[測試命令對象](http://grails.org/doc/latest/guide/testing.html#unitTestingControllers)。 – dmahapatro 2014-12-03 00:25:23

+0

@dmahapatro對不起,但我在提問之前已經查看了文檔的這一部分。我的命令對象使用一個服務。我想嘲笑這一點,並定義模擬方法的行爲。我猜我可以使用'@ ServiceUnitTestMixin',但不知道如何定義方法的行爲。 Grails文檔傾向於說明最明顯的。他們的Javadoc停了下來,沒有什麼可悲的。 – 2014-12-03 04:24:54

+0

我改變了使用getter而不是字段訪問的命令。 'getMovieRipSearchService()。search'。然後,我編寫了以下測試,但失敗後沒有發生調用錯誤。 @TestFor(MovieRipController) 類MovieRipControllerSpec延伸規格{ \t @Shared MovieRipSearchService mockService =假() DEF setupSpec(){ \t SearchMovieRipCommand.metaClass.getMovieRipSearchService = { - > \t \t mockService \t} } (){ \t //省略 \t then: ngSpace','',100) } } – 2014-12-03 18:01:40

回答

1

回答我的問題,這是我一直在使用元編程,模擬考試和什麼小Grails文檔中提供的混音工作。這個解決方案只有在命令訪問服務屬性而不是域(即使用getter,而不是域名)的情況下才有效,無論如何這不是一個壞的折衷。

幾乎我在網上看到的有問題的人的每一篇文章都抱怨缺少良好的文檔。如果人們不得不花費幾個小時甚至幾天的時間來計算如何對代碼進行單元測試,那麼Grails的快速開發仍然是一個錯誤的承諾。更何況,它也有助於更快地修復錯誤(我看到的情侶幾年來都是開放的)。

希望我的經驗能幫助別人。

@TestFor(MovieRipController) 
class MovieRipControllerSpec extends Specification { 

    /* For unknown reason, Spock mock doesn't work; throws NPE when defining interactions in test methods */ 
    @Shared def mockSearchService = mockFor(MovieRipSearchService) 

    def setupSpec() { 
     SearchMovieRipCommand.metaClass.getMovieRipSearchService = { -> 
      mockSearchService.createMock() 
     } 
    } 

    def setup() { 
     request.method = 'GET' 
     response.format = 'json' 
    } 

    void 'test that trailing space in the field name is trimmed during search command data binding'() { 
     setup: 
     params.fieldName = 'fieldNameWithTrailingSpace ' 
     params.fieldValue = null 
     params.max = 101 

     mockSearchService.demand.search { fieldName, fieldValue, max -> 
      assert fieldName == 'fieldNameWithTrailingSpace' 
      assert fieldValue == '' 
      assert max == 100 

      [terminator2MovieRipLite()] as List 
     } 

     when: 
     controller.show() 

     then: 
     mockSearchService.verify() 

     response.status == 200 
     response.json.size() == 1 

     response.json[0].title == 'Terminator 2 Judgment Day' 
    } 
}