2

Grails 2.1.1 アプリケーションで、'withFormat' を使用して応答を HTML または JSON としてレンダリングするコントローラーを単体テストしようとしています。ただし、HTML コンテンツ タイプに応答すると、クロージャーでラップして明示的に「render」を呼び出さない限り、テストで常に空の応答が返されます。JSON の場合、期待される応答が返されます。

コントローラ:

import grails.converters.JSON

class TestController {
def formatWithHtmlOrJson() {
    withFormat {
        html someContent:"should be HTML" 
        json {render new Expando(someContent:"should be JSON")  as JSON}
    }
}

テスト:

@TestFor(TestController)
class TestControllerTests {
    void testForJson() {
        response.format = "json"
        controller.formatWithHtmlOrJson()
        println("resp: $response.contentAsString")
        assert response.json.properties.someContent == "should be JSON"
    }

    void testForHtml() {
        response.format = "html"
        controller.formatWithHtmlOrJson()
        println("resp: $response.contentAsString")
        // fails here, response is empty
        assert response.text
        //never gets this far
        assert response.contentAsString.contains("HTML")
    }
}

上記のように、JSON の場合はこれで機能しますが、HTML の場合は、次のように html チェックをクロージャーでラップして明示的に render を呼び出さない限り、常に空の応答が返されます。

withFormat {
    html {
        render someContent:"should be HTML" 
    }

ドキュメントは、これを行う必要はないことを示唆しています。

withFormat {
    html bookList: books
    js { render "alert('hello')" }
    xml { render books as XML }
}

http://grails.org/doc/2.2.x/ref/Controllers/withFormat.htmlから

イライラすることに、grails のテストに関するドキュメントでは withFormat の使用について言及されていますが、xml/json をテストするための例のみが示され、html 応答については何も示されていません。

http://grails.org/doc/latest/guide/testing.html#unitTestingControllers

誰かがこの不一致を説明できますか、またはテストでそれを回避するにはどうすればよいですか?

4

3 に答える 3

3

最後にこれを理解しました。

ドキュメント ( http://grails.org/doc/latest/guide/testing.html#unitTestingControllers ) では、マップを返すアクションのテストでコントローラーの応答をテストするこの方法について言及しています 。

import grails.test.mixin.*
@TestFor(SimpleController)
class SimpleControllerTests {

    void testShowBookDetails() {
        def model = controller.showBookDetails()
        assert model.author == 'Alvin Plantinga' 
    }
}

withFormatを使用するコントローラ メソッドでも同じアプローチが機能します。

したがって、上記の元の例では:

withFormat {
    html someContent:"should be HTML" 
...

テストは次のようになります。

void testForHtml() {
    response.format = "html"
    def model = controller.formatWithHtmlOrJson()
    assert model.someContent == "should be HTML"
}

withFormatセクションではこのアプローチについて言及されていないため、ドキュメントは少し混乱しています。

他の誰かがこれに遭遇した場合、html ブロッ​​クがクロージャー内にある場合、マップは返されず、マップ エントリの値が返されることに注意してください。したがって、コントローラー コードの場合:

withFormat{
    html{
        someContent:"should be HTML" 
    }...

テストチェックは次のようになります。

     assert model == "should be HTML"

または、コントローラー コードを変更できる場合は、マップ内で結果を返すことで、ドット表記を使用して要素の値を確認できます。このコードの場合:

 withFormat {
    html {
        [someContent:"should be HTML"] 
    }....

テストチェックは次のとおりです。

assert model.someContent == "should be HTML"

また、HTML 型のクロージャを使用しない元の例では、値をマップとして返​​すことはできず、コンパイル エラーが発生します。

//Don't do this, won't compile
    withFormat {
        html [someContent:"should be HTML"]         
    ...
于 2013-04-24T15:10:11.093 に答える
0

試す

withFormat {
    html {
        println("html")
        [new Expando(test:"html")]
    }
}
于 2013-04-23T15:59:14.337 に答える
0

ドキュメントで提供されている提案では、a を使用せず、closureこの言葉遣いが含まれています」 .gsp ".

closureforを使用する場合、アクションまたはコンテンツhtmlに a を返す必要があります。この場合、コンテンツを使用しているため、レンダリングする必要があります。modelrenderhtml closure

クロージャーの使用 (ユースケースはパスしました)

withFormat{
   html {
      test: "HTML Content" //This will not render any content
      render(test: "HTML Content") //This has to be used
   }
}
于 2013-04-24T04:52:48.040 に答える