grails 2.4.4 (および 2.4.5) を使用して、次の小さなアプリケーションを作成しました。
grails create-app example
cd example
grails create-domain-class Book
次に、 Book.groovy を次のように編集しました
package example
class Book {
String title;
static constraints = {
}
}
次に、基本的なコントローラーを追加しました
grails> create-controller example.book
| Created file grails-app/controllers/example/BookController.groovy
| Created file grails-app/views/book
| Created file test/unit/example/BookControllerSpec.groovy
コントローラーを変更して、RestfulController を拡張します。
package example
import grails.rest.*
class BookController extends RestfulController<Book> {
static responseFormats=['json','xml']
BookController() {
super(Book)
}
}
UrlMappings をフックして、書籍を /api/books のリソースとして提供します。
class UrlMappings {
static mappings = {
"/api/books"(resources: "book")
"/"(view:"/index")
"500"(view:'/error')
}
}
最後に、BootStrap.groovy でいくつかの本を作成しました。
import example.*
class BootStrap {
def init = { servletContext ->
new Book(title: "Book 1").save(failOnError:true);
new Book(title: "Book 2").save(failOnError:true);
new Book(title: "Book 3").save(failOnError:true);
}
def destroy = {
}
}
それからgrails run-app
そして、すべてが良さそうです。example.Book コントローラがインデックス ページに表示されます。3 つの本は、json または xml として表示できます。
それでは、単体テストに進みます。
BookControllerSpec を次のように編集します
package example
import grails.test.mixin.TestFor
import grails.test.mixin.Mock
import spock.lang.Specification
@TestFor(BookController)
@Mock(Book)
class BookControllerSpec extends Specification {
def setup() {
new Book(title: "Unit Test Book 1").save(failOnError:true);
new Book(title: "Unit Test Book 2").save(failOnError:true);
new Book(title: "Unit Test Book 3").save(failOnError:true);
}
void "My Setup Worked"() {
given: "My setup ran"
when: "I ask for the count"
then: "I should get back 3"
Book.count() == 3;
}
void "I can access my Controller index method"() {
given: "My setup ran"
when: "I call index"
request.method="GET"
response.format="xml"
controller.index();
then: "I get an XML object back with 3 books"
println response.contentAsString
response.xml.book*.title.size()==3
}
}
最初のテストはパスし、2 番目のテストは失敗します。失敗したテストの println からの出力は、書籍の空の xml リストです。
<?xml version="1.0" encoding="UTF-8"?><list />
何が起こっているのかを調査しながら、親クラス (RestfulController) の index メソッドに注目しました。
そのメソッドを BookController にコピーすることで、単体テストがパスし始めます。
-- index メソッドをコピーした新しいバージョンの BookController --
package example
import grails.rest.*
class BookController extends RestfulController<Book> {
static responseFormats=['json','xml']
BookController() {
super(Book)
}
def index(Integer max) {
params.max = Math.min(max ?: 10, 100)
respond listAllResources(params), model: [("${resourceName}Count".toString()): countResources()]
}
}
インデックス メソッドを BookController にコピーしなくても、RestfulController のインデックス メソッドを機能させるために、仕様に追加する必要があるものは他にありますか?
BookController から直接実行すると への呼び出しがlistAllResources
機能するのに、RestfulController から実行すると行が返されない理由は何ですか。
上記の単体テストは、grails 2.3 用に書かれた Grails In Action ブックで説明されているその他の単体テストの修正版です。 http://www.manning.com/gsmith2/