Monday, February 25, 2008

Groovy Stub's

I've been getting the chance to use Groovy a lot more at work lately and it's allowed me to really dig deep into some of the features. One of those being the use of Stub's for Unit testing. This is a fantastic feature and really simple to use. Lets look at the following code below:



def Entries[] getFeed(feedUrl) {
def url = new URL(feedUrl)
def data = url.getText()

def xmlSlurper = new XmlSlurper()
def feed = xmlSlurper.parseText(data)

if (feedType.toLowerCase() == "rss") {
feed.channel.item.each { item ->
def rssItem = new Entries()
rssItem.title = item.title
rssItem.link = item.link
rssItem.description = item.description
rssItem.date = item.pubDate
println (rssItem)
entries.add (rssItem)
}
} else {
feed.entry.each { entry ->
def atomEntry = new Entries()

atomEntry.title = entry.title
atomEntry.link = entry.link[0].@href
atomEntry.description = entry.content
atomEntry.date = entry.published
entries.add (atomEntry)
}
}
return (Entries[]) entries.toArray()
}



This code is pretty straight forward in that we are taking a URL for an RSS feed and going to read the feed and create an Entries object for each entry in the feed (this is a great example of how to use Groovy to consume rss feeds). The problem with unit testing this is the following section:



def url = new URL(feedUrl)
def data = url.getText()


I needed a way to stub this out so I could isolate this code at the unit level. Using Groovy's StubFor was the perfect way, the following is what my unit test looked like:



def void testAtomFeed() {
def block = new RssDataBlock()
block.engineURL = "http://bob.com"
block.feedType = "atom"
def urlStub = new StubFor(URL)
urlStub.demand.getText {
return "my mock data"
}
urlStub.use {
def entries = block.getFeed("http://cnn.com")
assertEquals("", block.generateOutput(),
"Title:${title}\r\nDescription:${description}\r\nLink:${link}\r\nPublished Date: ${date}")
}
}



The import thing that is going on is we are creating a Stub for the URL class (new StubFor(URL)), and intercepting when the getText() method gets called we are going to return our sample data set. To use the stub you simply call urlStub.use and in the closure you execute your test. As you can see above, I call getFeed() with my bogus URL; and then I assert that the output I was expecting (generateOutput()pretty prints my output for me) is equal to what I actually got.

This is very powerful and makes my life a whole lot easier. The more I use Groovy, the more I'm impressed (I've even been able to convert some of my co-workers :) ). Stay tuned, I plan on posting about Groovlets next......