Grails: поведение list.contains в тесте кода против интеграции
Представьте, что есть форма для массового обновления группы логинов и их статусов; Используемая логика заключается в наличии скрытого поля, которое отслеживает все возможные идентификаторы и группу… например, радио-btns. позже через сервис, активируя все проверенные идентификаторы в нашем списке и деактивируя остальные:
def enabledLogins = toList(params.enabledLogins)
def allLoginIds = params.allLoginIds.toString().split(',')
loginService.updateLoginStatus(allLoginIds,enabledLogins)
вот определение сервиса
def updateLoginStatus(String[] allLoginIds, List<Long> enabledLoginIds) {
for (item in allLoginIds) {
def login = Login.get(item.toLong())
if (login) {
login.enabled = enabledLoginIds.contains(item.toLong()) ? true : false
login.save()
if (login.hasErrors()) {
login.errors.each { log.error(it) }
}
}
}
}
А вот и интеграционный тест:
def testUpdateLoginStatus() {
def id1 = createLogin().id
def id2 = createLogin().id
String[] allLoginIds = [id1 as String, id2 as String]
List<Long> enabledLoginIds = [id1]
loginService.updateLoginStatus(allLoginIds, enabledLoginIds)
def login1 = Login.get(id1)
def login2 = Login.get(id2)
assertTrue login1.enabled
assertFalse login2.enabled
}
Login createLogin() {
def now = System.currentTimeMillis()
def email = "int-test-" + now + "@somewhere.com"
def password = "Pwd" + now + "pwD"
def login = new Login(username: email, password: password, firstName: "Integration", lastName: "Test")
login.save(flush: true)
assertNotNull login.id
return login
}
Теперь вот проблема:
Приведенный выше код просто проходит тест интеграции, но не работает на практике, если я не вывожу toLong из
enabledLoginIds.contains(item.toLong())который в таком случае не проходит интеграционный тест... так что тип где-то как-то не так... но я не вижу его
Спасибо
Ps: Граальс 1.3.7
1 ответ
Все параметры выглядят как строки, поэтому код в вашем контроллере:
def enabledLogins = toList(params.enabledLogins)
Который создает список строк. Вот почему, если вы запустите приложение.toLong(), оно будет работать. Потому что тогда это делает:
["1", "2"].contains("1")
Вместо вашей текущей реализации с.toLong, в результате чего:
["1", "2"].contains(1)
Есть несколько вещей, которые я вижу здесь:
1) Помните, что дженерики - это только время компиляции (поэтому в целом они бесполезны) Так что, хотя у вас есть параметр (... , List<Long> enabledLoginIds)
в подписи вашего метода. Во время выполнения нет гарантии, что это будет список длинных.
2) Я обычно проверяю интеграцию через контроллер. Это дает вам немного лучший конец теста и помогает избежать подобных проблем. Где он проходит тест, но не работает на производстве, так что вы думаете, что с тестом что-то не так.