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 检查包装在一个闭包中并显式调用渲染,如下所示:

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

文档中提供的建议不使用 aclosure并且具有这种措辞“ Grails 搜索名为 grails-app/views/book/list.html.gsp 的视图,如果未找到则回退到 grails-app/views/book/list .gsp ”。

当您使用 aclosure时,html我们必须将 a 返回model到操作或render内容。因为在这种情况下,您正在使用html 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 回答