Question

I am trying to write an integration test in grails using an h2 database. I'm using h2 so I don't have to setup a database in the CI server. However I'm having problems initializing the data in my database.

This is what my test looks like right now:

class PathGeneratorServiceSpec extends Specification {

  def pathGeneratorService

  def setup() {
    PathSeed pathSeed = new PathSeed(id:1, seed:0).save()
  }

  void "getNextPath should return a string"() {
    when:
      def retVal = pathGeneratorService.getNextPath()

    then:
      retVal instanceof String
  }
}

However when I try to run my test I'm getting a NPE: Cannot get property 'seed' on null object

This is what my service looks like by the way:

public String getNextPath() {
    def seedValue = getNextSeed()
    def path = createPath(seedValue)
    return path
}

private def getNextSeed() {
    def seedValue
    PathSeed.withTransaction { txn ->
        def seed = PathSeed.lock(1)
        seedValue = seed.seed
        seed.seed++
        seed.save()
    }
    return seedValue
}
Was it helpful?

Solution

I think the problem is caused by your attempt to assign a value to the identity column. If you replace this:

PathSeed pathSeed = new PathSeed(id:1, seed:0).save()

with

PathSeed pathSeed = new PathSeed(seed:0).save()

and also replace:

PathSeed.lock(1)

with:

PathSeed.first()

Does that solve your problem? You should never need to explicitly assign a value to id, and you should avoid hardcoding ID values, e.g. PathSeed.lock(1)

Update

You asked in a comment

is there any way to lock the database using first?

No, but you can adapt the solution above to use pessimistic locking like so:

class PathGeneratorServiceSpec extends Specification {

  def pathGeneratorService
  private Long pathSeedId

  def setup() {
    pathSeedId = new PathSeed(seed:0).save().id
  }

  void "getNextPath should return a string"() {
    when:
      def retVal = pathGeneratorService.getNextPath(pathSeedId)

    then:
      retVal instanceof String
  }
}

public String getNextPath(id) {
    def seedValue = getNextSeed(id)
    def path = createPath(seedValue)
    return path
}

private def getNextSeed(id) {
    def seedValue
    PathSeed.withTransaction { txn ->
        def seed = PathSeed.lock(id)
        seedValue = seed.seed
        seed.seed++
        seed.save()
    }
    return seedValue
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top