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.