单元测试具有'withFormat'和html内容类型的控制器给出空响应,除非显式调用'render'

时间:2013-04-23 14:12:56

标签: unit-testing grails

在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

任何人都可以解释这种差异,或者我如何解决这个问题 测试

3 个答案:

答案 0 :(得分: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块在闭包内,则不会返回地图,而是返回map条目的值,因此对于控制器代码:

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"]         
    ...

答案 1 :(得分:0)

withFormat {
    html {
        println("html")
        [new Expando(test:"html")]
    }
}

答案 2 :(得分:0)

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

当您使用closure html时,我们必须将model返回到操作或render内容。由于在这种情况下您使用html closure,因此必须呈现内容。

使用Closure(您的用例已通过)

withFormat{
   html {
      test: "HTML Content" //This will not render any content
      render(test: "HTML Content") //This has to be used
   }
}