Friday, August 9, 2013

Groovy moonlighter mistake: Not all "method chaining" does what you might think


Setup
I am using Spock to help inject Groovy into our project and currently that means testing our new RESTful API.   We need to be able to send and receive both XML and JSON.    To test our POST method, I created a default Cart object and get the JSON representation.   I decided to try to use curl to call some of the methods, so for this POST method call, I needed to save the JSON to a file.  Later, I wanted to make sure the file was created.

Problem Code
The code below gets a NullPointerException calling the exists() method.

public void "POST Creates New Cart with JSON"() {
   when:
   File f = new File("cart.json").write(getDefaultCartJSON())
   
   def response = '''curl -X POST -i -d @cart.json --header "Content-Type:application/json"
          http://localhost:7001/restservices/carts'''.execute().text
  
    then:
    f.exists()
    response.startsWith("HTTP/1.1 201 Created")
  }
}

Root Cause:
The problem wasn't obvious immediately to me (hey I wrote it!).  The problem is the write() method returns a void, not the file object.

 File f = new File("cart.json").write(getDefaultCartJSON())

Corrected Code
Below is the corrected code.  So you don't always need to assign the result of a 'new' into a variable, even though that's how many of us learned to program.

public void "POST Creates New Cart with JSON"() {
   when:
   new File("cart.json").write(getDefaultCartJSON())
   
   def response = '''curl -X POST -i -d @cart.json --header "Content-Type:application/json"
          http://localhost:7001/restservices/carts'''.execute().text
  
    then:
    new File("cart.json").exists()
    response.startsWith("HTTP/1.1 201 Created")
  }
}

Wrap-up
Obviously this was not some major problem or break-through, just something to keep in mind as you write your code.   Maybe this will help prevent others from making the same mistake(s) I made. :-)

Hope it helps!

Thursday, August 8, 2013

Groovy moonlighter mistake: Spock requires JUnit to run inside Eclispe

Setup

I was rushing a bit the other day to get a new project setup in Eclipse.   The project is for some RESTful API work we are doing.  Naturally, I started looking for a way to inject Groovy into the process (regardless of how much resistance I continue to encounter from my colleagues).  :-)    Why not include the Spock testing framework I thought.  Great, if the team doesn't want to use Groovy, they can still write their test cases the old way, but I am going to inject Spock to the project!

Now I am off and running:
  • Eclipse project created: check
  • Added Groovy Nature to the Eclipse project: check
  • Included the Spock jar in the build path: check
  • First test case written using Spock and it compiles: check
  • Run my test case from within Eclipse: WTF, Eclipse where's the JUnit menu option (screenshot below)

Resolution:
Spock requires JUnit to run inside Eclipse (duh!).   So I added the JUnit jar to my build path and now as you can see in the screenshot below - all is better with my world - now I can run my Spock tests within Eclipse!


I have to thank danveloper for the tagline "Groovy moonlighter".  We were exchanging emails about one of his projects when I complained that my Groovy practice is limited to nights and weekends.  At that point he called me a 'Groovy Moonlighter".   Thanks Dan!

Hope this helps!