Grails 2.0 单元测试自定义标签库

发布于 2024-12-29 15:27:42 字数 1943 浏览 3 评论 0原文

我编写了一个自定义标签库,以便可以以简单的方式显示对象的属性。它允许我打电话,

<g:property label="Name" property="${user.name}"/>

这使我的观点保持简短和一致,并允许我快速做出改变。我的标签库代码如下:

def property = {attrs, body ->
    def startingHtml = "..."
    def endingHtml = "..."

    out << startingHtml
    renderField(attrs.property)
    out << endingHtml
}

def renderField(property) {
    if (property instanceof Collection) {
        property.each { out << it + "</br>" }
    } else if(property instanceof Address){
        renderAddress(property)
    } else {
        out << property
    }
}

def renderAddress(address) {
    out << "Address Render Logic Here"
}

我试图围绕此代码添加一些单元测试,因为其中有逻辑。使用此处找到的示例( http://grails.org/doc/latest/guide /testing.html#unitTestingTagLibraries)我开始添加一些测试。我的标签当前处理的前两个场景是字符串和集合,我能够正确测试它们(下面的前两个测试)。我需要测试的最后一个场景是一个 Address 对象(它只是一个带有 String 属性的 POGO)。我似乎找不到一种方法来测试将对象作为属性传递到标签库中。

@TestFor(PropertyTagLib)
class PropertyTagLibTests {

@Test
void propertyTagShouldRenderPropertyInsideOfTDWhenPropertyIsAString() {
    String result = applyTemplate('<g:property label="something" property="someTextValue"/>').trim()

    assert result.contains('someTextValue')
}

@Test
void propertyTagShouldRenderList() {
    String result = applyTemplate('g:property label="something" property="[\"one\", \"two\", \"three\"]"/>').trim()

    assert result.contains("one</br>two</br>three</br>")
}

@Test
void propertyTagShouldRenderPropertyInsideOfTDWhenPropertyIsAnAddress() {
    def address = new Address(line1: "Line 1")
    String result = applyTemplate('<g:property label="something" property="${address}"/>').trim()

    assert result.contains("Address Render Logic Here")
}
}

当其中一个属性是对象时,如何测试我的标签库?

I have a custom tag lib that I wrote so that I can display properties of an object in an easy fashion. It allows me to call

<g:property label="Name" property="${user.name}"/>

Which keeps my views short and consistent as well as allows me to make changes quickly. My taglib code is as follows:

def property = {attrs, body ->
    def startingHtml = "..."
    def endingHtml = "..."

    out << startingHtml
    renderField(attrs.property)
    out << endingHtml
}

def renderField(property) {
    if (property instanceof Collection) {
        property.each { out << it + "</br>" }
    } else if(property instanceof Address){
        renderAddress(property)
    } else {
        out << property
    }
}

def renderAddress(address) {
    out << "Address Render Logic Here"
}

I'm trying to add some unit tests around this code because there is logic in it. Using the examples found here ( http://grails.org/doc/latest/guide/testing.html#unitTestingTagLibraries) I started adding some tests. The first two scenarios that my tag currently handles are String and Collection, which I was able to test correctly (first two tests below). The last scenario that I need to test is an Address object (which is just a POGO with String attributes). I can't seem to find a way to test passing an object as an attribute into a tag lib.

@TestFor(PropertyTagLib)
class PropertyTagLibTests {

@Test
void propertyTagShouldRenderPropertyInsideOfTDWhenPropertyIsAString() {
    String result = applyTemplate('<g:property label="something" property="someTextValue"/>').trim()

    assert result.contains('someTextValue')
}

@Test
void propertyTagShouldRenderList() {
    String result = applyTemplate('g:property label="something" property="[\"one\", \"two\", \"three\"]"/>').trim()

    assert result.contains("one</br>two</br>three</br>")
}

@Test
void propertyTagShouldRenderPropertyInsideOfTDWhenPropertyIsAnAddress() {
    def address = new Address(line1: "Line 1")
    String result = applyTemplate('<g:property label="something" property="${address}"/>').trim()

    assert result.contains("Address Render Logic Here")
}
}

How can I test my taglib when one of the attributes is an object?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

高冷爸爸 2025-01-05 15:27:42

applyTemplate() 的声明如下所示:

String applyTemplate(String contents, Map model = [:])

标签参数通过 model 传递。

您的测试可能如下所示:

@Test
void propertyTagShouldRenderPropertyInsideOfTDWhenPropertyIsAnAddress() {
    String result = applyTemplate('<g:property label="something" property="${address}"/>', [address : new Address(line1: "Line 1")]).trim()

    assert result.contains("Address Render Logic Here")
}

The declaration of applyTemplate() looks as follows:

String applyTemplate(String contents, Map model = [:])

Tag parameters are passed through model.

Your test might look as follows:

@Test
void propertyTagShouldRenderPropertyInsideOfTDWhenPropertyIsAnAddress() {
    String result = applyTemplate('<g:property label="something" property="${address}"/>', [address : new Address(line1: "Line 1")]).trim()

    assert result.contains("Address Render Logic Here")
}
紫南 2025-01-05 15:27:42

因此,我通过“消除中间人”并绕过 applyTemplate() 并直接转到执行逻辑的方法来解决这个问题。这不太理想,原因有二:
1) 我并不是断言属性标签与 renderField 连接在一起,但希望我的其他测试仍然使用 applyTemplate() 确保这一点。
2)在现实世界中,TagLib 中的 out 是一个输出编写器,在我的测试中,我将其创建为一个列表(我可以这样做,因为您可以执行左移的任何操作都足够了) 。

我喜欢使用列表的原因是它有助于维护顺序。

@Test
void renderFieldShouldRenderAddress() {
    def address = new Address(line1: "Line 1", line2: "Line 2", line3: "Line 3",
        city: "City", state: "ST", zipCode: "12345", country: "USA",
        buildingNumber: null, buildingName: null, roomNumber: null
        )
    def tagLib = new PropertyTagLib()
    def results = []
    tagLib.metaClass.getOut = {
        results
    }

    tagLib.renderField(address)

    assert "Line 1" == results[0]
    assert "<br />" == results[1]
    assert "Line 2" == results[2]
    assert "<br />" == results[3]
    assert "Line 3" == results[4]
    assert "<br />" == results[5]
    assert "City, ST 12345" == results[6]
    assert "<br />" == results[7]
    assert "USA" == results[8]
    assert "<br />" == results[9]
    assert 10 == results.size()
}

有什么想法吗?

So I solved this by "cutting out the middle man" and circumventing the applyTemplate() and directly going to the method that does the logic. This isn't quite ideal because of two reasons:
1) I'm not asserting that the property tag is hooked up with renderField, but hopefully my other tests which still use applyTemplate() ensure that.
2) In the real world out in a TagLib is a output writer and in my test I've created it as a list (I can do this since anything you can do a left shift on will suffice).

What I do like about using a list is it helps assert order.

@Test
void renderFieldShouldRenderAddress() {
    def address = new Address(line1: "Line 1", line2: "Line 2", line3: "Line 3",
        city: "City", state: "ST", zipCode: "12345", country: "USA",
        buildingNumber: null, buildingName: null, roomNumber: null
        )
    def tagLib = new PropertyTagLib()
    def results = []
    tagLib.metaClass.getOut = {
        results
    }

    tagLib.renderField(address)

    assert "Line 1" == results[0]
    assert "<br />" == results[1]
    assert "Line 2" == results[2]
    assert "<br />" == results[3]
    assert "Line 3" == results[4]
    assert "<br />" == results[5]
    assert "City, ST 12345" == results[6]
    assert "<br />" == results[7]
    assert "USA" == results[8]
    assert "<br />" == results[9]
    assert 10 == results.size()
}

Any thoughts?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文