title: Data Driven Testing in Grails with Spock and a Service class
body: <p>I'm trying to write an integration test for my Grails service class using Spock.</p>
  
  <p>To get some data to drive the test, I have a query like this:
  <code>"select column1, column2, column3 from table where column1 = ?"</code></p>
  
  <p>I get the results from that query using a custom service that we wrote. Basically, it wraps up Groovy's Sql class and handles opening and closing database connections for me. I can inject that into my integration test just fine using Grails' typical dependency injection. However, I <em>can't</em> seem to use it to retrieve data for a data-driven test. Here's my test class:</p>
  
  <pre><code>class MyServiceSpec extends Specification {
      def myService
      def sqlService
      @Shared tsQuery
      @Shared ts
  
      def setupSpec() {
          tsQuery = "select column1, column2, column3 from table where column1 = ?"
          ts = sqlService.rows(tsQuery, ['someSuch'])
      }
  
      def "test a feature"() {
          setup:
              def ts = sqlService.rows(tsQuery)
              def results = myService.getTimesheets(thing1, thing2, thing3)
          expect: 
              //some appropriate expectations based on the data here
          where:
              timeSheet &lt;&lt; ts
              thing1 = timeSheet.column1
              thing2 = timeSheet.column2
              thing3 = timeSheet.column3
      }
  }
  </code></pre>
  
  <p>That throws an error that I'm not allowed to call sqlService in the setupSpec() block: </p>
  
  <pre><code>Only @Shared and static fields may be accessed from here
         ts = sqlService.rows(tsQuery)
              ^
  </code></pre>
  
  <p>The problem is, if I make sqlService <code>@Shared</code>, Grails dependency injection doesn't work and it just creates a null object. Same thing if I try making it static (as in <code>static def sqlService</code>).</p>
  
  <pre><code>java.lang.NullPointerException: Cannot invoke method rows() on null object
  </code></pre>
  
  <h1>Workarounds I've Tried</h1>
  
  <h2>A new SqlService Instance in setupSpec</h2>
  
  <p>I tried just initalizing a new SqlService instance, like this in my setupSpec block:</p>
  
  <pre><code>    def setupSpec() {
          tsQuery = "select column1, column2, column3 from table where column1 = 'someSuch'"
          def sql = new SqlService()
          ts = sql.rows(tsQuery)
      }
  </code></pre>
  
  <p>That just gives an error </p>
  
  <p>| Error 2014-06-13 14:52:10,932 [main] ERROR common.SqlService  - Error in sqlQuery: Ambiguous method overloading for method groovy.sql.Sql#.
  Cannot resolve which method to invoke for [null] due to overlapping prototypes between:
      [interface javax.sql.DataSource]
      [interface java.sql.Connection]</p>
  
  <h2>Defining sqlService in the setup method</h2>
  
  <p>If, instead of using setupSpec() I just use setup(), and put a <code>def sqlService</code> in it, then the sqlService object is null and thus I get a "Cannot invoke method rows() on null object" error.</p>
  
  <p>If I instead <code>def sqlService = new SqlService()</code>, then I get the same error as if I did that in setupSpec(), saying that there are overlapping prototypes between javax.sql.Datasource and java.sql.Connection.</p>
  
  <h1>Bottom Line</h1>
  
  <p>Anyone know how I can use another service class as a data provider in a Spock test?</p>