简体   繁体   中英

Grails 2.0 Unit Testing Custom Tag Lib

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?

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")
}

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?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM