Интеграционное тестирование Grails NPE с использованием h2
Вопрос
Я пытаюсь написать интеграционный тест в Grails, используя базу данных h2.Я использую h2, поэтому мне не нужно настраивать базу данных на сервере CI.Однако у меня возникли проблемы с инициализацией данных в моей базе данных.
Вот как сейчас выглядит мой тест:
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
}
}
Однако, когда я пытаюсь запустить тест, я получаю NPE: Cannot get property 'seed' on null object
Кстати, вот как выглядит мой сервис:
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
}
Решение
Я думаю, что проблема вызвана вашей попыткой присвоить значение столбцу идентификаторов.Если вы замените это:
PathSeed pathSeed = new PathSeed(id:1, seed:0).save()
с
PathSeed pathSeed = new PathSeed(seed:0).save()
а также заменить:
PathSeed.lock(1)
с:
PathSeed.first()
Это решает вашу проблему?Никогда не нужно явно присваивать значение id
, и вам следует избегать жесткого кодирования значений идентификатора, например. PathSeed.lock(1)
Обновлять
Вы спросили в комментарии
Есть ли способ сначала заблокировать базу данных?
Нет, но вы можете адаптировать приведенное выше решение для использования пессимистической блокировки следующим образом:
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
}